home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 11
/
Cream of the Crop 11-2.iso
/
os2
/
edmi3_9.zip
/
edmi3-9.INF
(
.txt
)
< prev
next >
Wrap
OS/2 Help File
|
1995-11-06
|
380KB
|
4,684 lines
ΓòÉΓòÉΓòÉ 1. Nov 1995 Title Page ΓòÉΓòÉΓòÉ
The Electronic Developer's Magazine for OS/2
Portions copyright (c) by IQPac Inc.
Volume 3, issue 9
Administrivia
EDM/2 3-9 is finally out! Last month, I was extremely busy with many things,
not the least of which were preparing for ColoradOS/2 and converting old issues
to native HTML format, so I passed the ball to Carsten. Unfortunately, Carsten
never produced an entire issue, so after much trial and error and with what
little help I could offer from Colorado, he finished after October 15; we
decided that, given the slimness of the issue, we would push it to November
since we were expecting more submissions from other authors.
A few notes before I sign off for the month:
In the mailing list, we are conducting an impromptu vote regarding the
format that you would prefer the magazine to be published in. The
choices are HTML, INF, or "other". The results will have some influence,
but do not assume that they will completely influence our direction. I
highly suggest that you send me email (os2man@panix.com) to let me know
which you prefer.
The Web site is growing rapidly! Issues 3-5 through this one are now
present in native, well-organized HTML format. Additionally, a new
Content Index has been added to allow you to browse a list of all of the
available submissions and follow the appropriate link when you've found
what you're looking for. We're excited about this and plan to enhance it
in different ways to make it as useful as possible for you.
Also on the Web site are my notes from ColoradOS/2. If you weren't able
to attend, you can still read about the things you should have seen and
heard during that week.
Carsten, assuming the role of publisher, wrote this section originally and his
text is below. Enjoy!
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Well, this month the worst finally happened: Larry got too busy doing other
important things (among which is converting old issues to HTML!) to do this
issue, so here I am, starting late, and going slow. It has been a long and
hard month, but there were a few highlights.
Already there are many reports of people buying some other 32-bit operating
system, and getting so disappointed that they took it back and bought Warp. Of
course, this is not what everyone is doing, but every little bit helps. We
need to be ready for these people with lots of great high-quality OS/2 apps,
so everybody get cracking right now!
A new fixpack (10) is out, and it has received mixed reviews. There are also
two unauthorized fixpacks out there (11 and 12), and although I wouldn't
recommend an unauthorized fixpack, it sounds as if things are heading in the
right direction. Fixpacks 9 and 10 broke some things in the REXX DLL, but
supposedly these are fixed again in fixpack 12. One of the things which was
broken in 9 and 10 was the VRPrompt function in VX-REXX, which uses an
automatically sized entry field. It turns out that the entry field itself was
broken, and IBM seems to have admitted this. Hence the re-fix in fixpack 12.
Included with this issue is the latest round of bugfixes and updates for the
editor which has been developed in the last few issues. Look for
smaled95.zip.
If the format is a little odd here and there, it is because I didn't have time
to go around and fix everything. It should be readable, though. That is
about all I have to say here. Now we continue on with the rest of this
slightly slim issue...
Title Page - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 2. Copyright Notice ΓòÉΓòÉΓòÉ
Copyright Notice
EDM/2 is published by IQPac Inc. IQPac Inc. can be reached via U.S. Mail at
the following address:
IQPac Inc.
7 East Broadway, Box 804
New York, NY 10038
U.S.A.
Editor-in-chief Larry Salomon Jr.
Associate editor Carsten Whimster
Contributing editor Gordon Zeglinski
CEO/President Larry Salomon Jr.
All material is copyrighted by its original author. No part of this magazine
may be reproduced without permission from the original author.
This publication may be freely distributed in electronic form provided that
all parts are present in their original unmodified form. A reasonable fee may
be charged for the physical act of distribution; no fee may be charged for the
publication itself.
Neither IQPac Inc. nor this publication are affiliated with International
Business Machines Corporation.
OS/2 is a registered trademark of International Business Machines Corporation.
Other trademarks are property of their respective owners. Any mention of a
product in this publication does not constitute an endorsement or affiliation
unless specifically stated in the text.
The OS/2 Accredited Logo is a trademark of International Business Machines
Corporation and is used by IQPac Inc. under license. This On-line Publication
is independently produced by IQPac Inc. and IBM is not responsible in any way
for its contents.
IQPac Inc. is an accredited member of the IBM Independent Vendor League.
Copyright Notice - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 3. Letters ΓòÉΓòÉΓòÉ
Letters
To write to EDM/2, send your email to os2man@panix.com and use the Subject:
line "Letters".
Appreciations!
Kalin Wilson (kwilson@mnsinc.com) writes:
Just wanted to send along my appreciation for your great product! I have been
reading your magazine for several months now and have managed to catch up on
many of the back issues. I have really learned a lot. I think I get more out
of EDM/2 than OS/2 Developer or any other programming mag I get. Your web page
is a big bonus. I have been archiving all the issues not on my Hobbes CDROM but
it's nice to know I can get any issue from the web site.
You're on my hotlist!
EDM/2 (Carsten) Responds:
That's the same way I felt about EDM/2 when I first started reading it. I hope
we can continue to provide this kind of service to OS/2 programmers everywhere,
and if you should ever want to contribute an article or a column, you know
where to reach us.
Thank you!
Niall Kavanagh (niall@peersa.iii.net) writes:
Just a quick note to say "Thank you!". Armed with EDM/2- Intro. to PM
programming and _Real World Programming for OS/2_ I have successfully completed
my first PM application! Keep up the great work!
EDM/2 (Carsten) Responds:
That is also one of my favorite books. There are other great ones, though. Be
sure to check the book review column from time to time. So, can we see your
program? <grin>
Letters - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 4. Announcements ΓòÉΓòÉΓòÉ
Announcements
Bullet Database Engine Toolkit for 32-bit Compilers
Contact: Cornel Huth
/e-mail: cornel@crl.com
San Antonio, Texas - Bullet/2 for OS/2 is a thread-safe, multi-process capable
database engine toolkit. It provides pre-built and tested access methods to
data and index files for application programmers. It is not an end-user
Database Management System (DBMS), but it is a tool that may be used to develop
one. Bullet is compact, efficient, and very fast. Bullet can be configured to
use custom key-build, sort-compare, and expression- parser routines to extend
the built-in functionality. Rules are few; possibilities are great.
The standard data format is DBF (dBASE 3+ and later). The supported memo
format is DBT (dBASE 4 and later). Index-only support can be enabled and with
this any data file format may be used (the data maintained by the programmer
then). Also, the DBF standard may be extended by using binary field values and
fields larger than 255 bytes. Index files are NLS- compatible and use an
efficient b-tree structure. Files may be any size supported by the OS, up to
4GB. Up to 1024 files may be opened and in use by any one process, with any
number of processes active.
The Bullet API consists of a wide assortment of routines, from low-level OS
calls to high-level transaction-list routines that can process hundreds of
files per transaction, with roll-back on error. Network and multi-user support
is included, and makes use of operating system features such as atomic
re-locking, and shared locks that allow other processes read-access to locked
files.
Bullet is simple to use and works the way you are used to working.
Documentation and samples included are for C or C++ compilers, but any compiler
supporting 32-bit DLLs may be used.
Pricing is available in three options, depending on total open files needed,
simultaneous processes running, and DLL or LIB requirements. Price starts at
$99 US. This release includes a try-before-you-buy version with the same
functionality as is available in the $99 option (100 open files, 2 processes),
and may be used for evaluating Bullet before purchase. The try-before-you- buy
version for OS/2 is located at the following locations:
FTP: - ftp.crl.com /users/co/cornel/database/blt2_203.zip
WWW: - ftp://ftp.crl.com/users/co/cornel/database/blt2_203.zip
BBS: - 1(210)684-8065 after business hours only ( 5pm-9am Central)
The filename is currently blt2_203.zip, but the last three digits will change
with future releases. Alternate sites include the SimTel archives (primary
site being oak.oakland.edu), Hobbes (hobbes.nmsu.edu), and on CompuServe, to
name a few. Check the language and database directories for Bullet (blt*).
Bullet is now available for:
Bullet/2 for OS/2: Includes DLL, import library, online and printer-ready
manuals. The API reference is available in either manual, with the tutorial
and additional source examples in the online version. A demo EXE program,
along with source, is also included. Printed documentation and the LIB
version of the library code are also available.
Bullet/X for 32-bit DOS extenders is to be available by the end of the month
and offers essentially the same features as Bullet/2, except it is for MS-DOS
platforms (DOS extender/DPMI-compliant). The Windows Win32 version is to
follow soon after.
Bullet 1 has been available for 16-bit compilers since 1992, and these are
available today as bltc125.zip, bltw125.zip, and bltq125.zip, for DOS C/C++,
Window 3.x, and DOS BASIC compilers, respectively, at the sites listed above.
For more information, visit any of the sites listed and download the
evaluation files, or e-mail to cornel@crl.com.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Multi-Voice and Multi-Fax Toolkit Released
Montreal, September 1995:
ITI Logiciel (ITI Software) announce the release of the OS/2 version of their
Multi-Voice and Multi-Fax programmer's toolkit.
Multi-Voice and Multi-Fax can be used to create voice processing application
such as: voice mail, automated attendant, fax-on-demand, fax broadcasting,
interactive voice response. As a high level 'C' toolkit, it is as easy to use
as any script language, but offers speed and flexibility of the 'C' language.
Here's description of the two products.
Multi-Voice Version 4.0
ITI Software proudly presents MULTI-VOICE Version 4.0, the complete set of
tools to write multi-line voice applications on OS/2 for most of the voice
processing boards available today.
Multi-Voice Product Description
MULTI-VOICE gives you a very high level C interface to the voice board
features. With a single function call, you can play or record a voice file.
You can play date and time, numbers, spell strings. Your Multi-Voice programs
can detect the callers Touch-Tones or rotary pulses, even voice recognition is
available in some versions. Never before has it been easier to integrate a
multi-line telephone interface to your C programs.
MULTI-VOICE has its own multi-tasking interface. You can run the same task on
all lines in the system or different tasks on certain lines. For most
applications, the multi-tasking is completely transparent and there is no need
for the programmer to have multi-tasking programming experience.
MULTI-VOICE brings the full power of voice processing boards to your finger
tips with the speed and ease of use of Borland's C/C++ 2.0 for OS/2.
Multi-Voice Example Programs
A Multi-User Multi-Line Telephone Answering program is provided to give
examples of how to call most functions in the library. The source code is
included, so this program can be modified to suit your own needs. We also
provide all the pre-recorded prompts used by this program. Many other example
programs are also provided with makefiles for all supported compilers.
Voice Boards Supported
Dialogic D4xx, D12xx, AMX, VRxxx Rhetorex RDSPxxxx NewVoice NVx00 Bicom xLS
Linkon's FC3000 & FC4000 Pika's V12 and InLine Series Talking Technology's
Power Line II
Portability
The programs written with Multi-Voice for any voice board can be ported
without any modifications for use with other voice boards. ITI Software
offers C libraries for all the supported boards, which reduces the
programmer's work to simply recompiling programs for the appropriate hardware.
And we're always working to implement new manufacturer's products.
System Requirements
IBM PC or compatible running DOS 3.3 or higher (6.2 recommended) Any of the
supported Voice Processing boards C/C++ Compiler: Borland's V2.0 for OS/2
Talking Clock Sample Program
/*
** This example program shows how easy and clear it is to program
** Multi-Line Voice Response applications using MULTI-VOICE Version 4.0.
**
** The program plays the current date and time on all lines available in
** the system. It answers the phone, plays a little introduction message,
** asks the user to press 1 for FRENCH, 2 for ENGLISH or 3 for SPANISH
** and it plays the date and time in the selected language, in the format
** Week Day, Month Day, Hour and Minutes.
*/
#include "stdio.h"
#include "MV_Util.h"
#include "MultiVox.h"
#define TIMEOUT 10
#define RETRY 3
#define PROMPT_DIR "PROMPTS"
void far LineHandler ( )
{
char answer;
MVU_LANGUAGE language;
MVU_DATE date;
MVU_DATE_FIELD date_field;
MV_StartLH ( );
while (MV_Running)
{
MV_Answer (1); /* answer phone after 1 ring */
if (MV_Result ( ) == MV_SUCCESS)
{
MV_Play ("intro.v", MV_AbortOnDtmf);
MVU_ReadMenu (PROMPT_DIR, "language.v", "err.v", & answer,
"123", TIMEOUT, RETRY);
if (MV_Result ( ) == MV_SUCCESS)
{
switch (answer)
{
case '1' : language = MVU_French; break;
case '2' : language = MVU_English; break;
case '3' : language = MVU_Spanish; break;
}
MVU_GetDateTime (date);
date_field = MVU_WDAY | MVU_MDAY | MVU_HOUR | MVU_MIN;
MVU_PlayDate (PROMPT_DIR, date, date_field,
MV_NoAbortOnDtmf, language);
MV_Play ("goodbye.v", MV_AbortOnDtmf);
}
}
MV_OnHook ( );
}
MV_StopLH ( );
}
void main (void)
{
MV_AllLineHandlers = LineHandler;
if (MV_Start ( ) == MV_SUCCESS)
{
MV_WaitEscape ( ); /* Waits until the ESCAPE key is pressed */
MV_Stop ( );
}
else
printf ("Initialization error");
}
Contact us for a complete list of functions provided.
All this for only $799 US
Multi-Fax Version 2.0
ITI Software introduces MULTI-FAX, the complete set of tools to write
multi-line fax applications for any CAS facsimile boards on OS/2.
Multi-Fax Product Description
The MULTI-FAX toolkit allows programmers (experienced or not) to write
applications which handle fax transmission. The toolkit can handle up to ten
fax boards simultaneously in a single PC.
MULTI-FAX will send any ASCII files, PCX or DCX graphic files without format
conversion. You can send multiple documents in a single call.
Used along with ITI Software's MULTI-VOICE toolkit, the MULTI-FAX toolkit
allows programmers to create highly sophisticated software to handle all
aspects of telephone interfacing. Applications such as Fax-Mail, Document
Broadcasting and Store-And-Forward can be implemented with minimum effort.
Multi-Fax Example Programs
Many example programs are provided to show how to call most procedures and
functions. You can modify these programs to suit your own needs.
System Requirements
IBM PC or compatible running DOS 3.3 or higher (5.0 recommended) Any CAS
compatible Fax Processing board. C/C++ Compiler: Borland's V2.0..V4.5,
Borland's Turbo V2.0..V3.0 or Microsoft V5.1..V8.0.
Fax Sending Sample Program
#include "stdio.h"
#include "MultiFax.h"
void main (void)
{
int fax_handle
/* Start MULTI-FAX and verify if there is a FAX board in the PC */
if (MF_Start () == 0)
{
printf ("No board found. \n");
exit (-1);
}
/* Create a fax entry. */
fax_handle = MF_CreateFax ();
/* Add company logo on cover page. */
MF_AddLogo (fax_handle, "logo.pcx");
/* Add a message to the cover page. */
MF_AddCoverPageText (fax_handle, "This is the cover page message.");
/* Add ASCII text file "FAX.TXT" and graphic document "FAX.DCX". */
MF_AddDocument (fax_handle, MF_ASCII_80, "fax.txt", MF_LETTER);
MF_AddDocument (fax_handle, MF_DCX, "fax.dcx", MF_LETTER);
/* Send it using highest resolution */
MF_SetResolution (fax_handle, MF_FINE);
MF_SetDestinationName (fax_handle, "Your Name");
MF_SetSenderName (fax_handle, "ITI Software");
MF_Send (fax_handle, MF_ANY_BOARD, "555-1212");
MF_FreeFax (fax_handle);
}
Contact us for a complete list of functions provided.
All this for only $299 US
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Rexx Symposium Dates Announced
Reserve May 13-15 next year for the Rexx Symposium and meeting of the Rexx
Language Association. We will meet in Austin, Texas, and have negotiated low
lodging rates at the Hyatt Regency. The Call for Speakers and more
information will follow.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
OS/2 Electronic Magazines
OS/2 Warp Weekly -
gopher://os2info.austin.ibm.com/11/nl/os2news/os2news.70.
OS/2 Warp Monthly - http://www.austin.ibm.com/pspinfo/newsletters.html
IBM NetNews Magazine - http://www.ibm.com/mag/netnews/
OS/2 Warp Flash Magazine -
http://www.iceonline.com/home/duncans/warpflash.html
OS/2 Developer Magazine - http://www.mfi.com/os2dev/os2maginf.html
OS/2 Connect Magazine -
http://warp.eecs.berkeley.edu/os2/warppage/connect/toc.html
Inside OS/2 Magazine - http://www.cobb.ziff.com/~cobb/os2/
IBM Personal Software Magazine -
http://www.austin.ibm.com/pspinfo/pcugpsm.html
IBM Personal Systems Magazine - http://pscc.dfw.ibm.com/psmag/index.html
IBM Software Quarterly Magazine - http://pscc.dfw.ibm.com/sq/enter.htm
[Editor's note - We still get no respect. Sigh.]
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
New GNU Fortran Available
The new version of GNU Fortran (g77-0.5.16) has been ported to emx.
It's available for anonymous ftp on:
ftp.uni-stuttgart.de - /pub/systems/os2/emx0.9a/contrib
ftp.leo.org - /pub/comp/os/os2/gnu/emx+gcc/contrib
ftp.cdrom.com - /pub/os2/incoming
hobbes.nmsu.edu - /incoming
Look for g77bin.zip (binaries) and g77src.zip (source).
This port of g77 uses now the backend of gcc-2.7.0. The executables
(g77bin.zip) should work with gcc-2.6.3 binaries, too.
Please send bug reports for g77 to fortran@gnu.ai.mit.edu, except for bugs
introduced by the port, which should be reported to me. If you are not sure,
send bugs to me.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Contact: Dick Goran
C F S Nevada, Inc.
Voice: 1-800-864-2358, 1-702-732-9616
FAX: 1-702-732-3847
Internet: dgoran@cfsrexx.com
CompuServe: 71154,2002
Free OS/2 Related Drawings on the Internet
Las Vegas, Nevada (9/28/95) -- Beginning on October 1, 1995 C F S Nevada, Inc.
will offer free monthly drawings at its Internet World Wide Web site
<http://www.cfsrexx.com>. The winners of the monthly drawings will each be
entitled to receive a complimentary copy of C F S Nevada, Inc.'s
award-winning, best selling REXX Reference Summary Handbook by Dick Goran or a
complimentary key to enable its new MKWINOS/2 program product. MKWINOS/2
creates OS/2 Desktop objects that are equivalent to your Windows Program
Manager and its contents. Full details about both the REXX Reference Summary
Handbook and MKWINOS/2 will be found on C F S Nevada, Inc.'s WWW site.
Though not the first WWW giveaway, this drawing is one of the few that will
offer entrants a chance each month to win multiple awards. The rules
governing the drawing are listed on C F S Nevada, Inc.'s home page.
The only hardware requirement necessary to complete an entry form for the
drawing is a WWW browser that supports form submission. It is not necessary
that the entrant be running OS/2.
C F S Nevada, Inc. is a Las Vegas based producer and publisher of OS/2
related software and publications as well providing commercial OS/2 training.
Links on their WWW site are provided for OS/2 related hardware and software as
well as some unusual, non-computer related sites.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Bubble Hint Custom Control for OS/2 PM
For more information: http://www.secant.com or info@secant.com
Now you can add bubble hints to any OS/2 program with our new Hint Bubble
Custom Control. You can attach them to any control, such as those confusing
toolbar buttons, and they will pop up after a specified time period to provide
addtional information. This control is provided with a "C" interface only,
although it may come out in the next release of the ObjectPM Control Pack with
all the wrapper classes. Everything you need is included -- header files,
libraries and DLL's. This is a "teaser" to drum up interest in our custom
control package and OS/2 custom controls in general.
No source provided, but may be distributed with any executable royalty-free.
Come and get it from our Web page at http://www.secant.com. Please do not
post on any other ftp site, as we would like to monitor interest by counting
ftp'd copies.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Stardock's Object Desktop is Here
Stardock Systems will begin shipping its Object Desktop on October 2, 1995.
Targeting both the corporate and retail markets, Object Desktop is an advanced
desktop environment that "turbo-charges" OS/2, improving performance,
flexibility, and ease of use.
Object Desktop enhances the existing OS/2 environment with updated icons,
frame controls, and command buttons, and adds new tools designed to boost
productivity and system performance. The new features include the Object
Navigator, Control Center, Keyboard LaunchPad, Object Archives, and HyperDrive
and HyperCache features.
"I haven't been this excited about a product since OS/2 Warp itself." said
David Barnes, Senior Marketing Manager at IBM Personal Software Products. "My
competitors recently released a product that has some nice features. But
Object Desktop gave me everything they have and a lot more (and on a more
solid foundation--OS/2 Warp). Object Desktop will be the first thing I
install on any of my systems from now on."
Object Desktop carries a suggested retail price of $99.95. Stardock expects
the typical street price to be significantly less than that. Site licensing
and wholesale pricing sheets can be obtained from Stardock at 313-453-0328
(fax 313/453-1480).
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
I've put together a new version of my screen saver "Blackout." The program is
intended for DPMS, or "Green" monitors which can be shut off automatically by
using this program; this is accomplished by turning off the syncronization
pulses to the monitor. The screen saver has three modes of saving: 1) it
reduces colour intensity on screen, and 2) it sets the monitor in suspend
mode, and 3) it switches the monitor off. No fancy graphics, but it does the
job - saves the screen.
The program is free and is distributed with source code. I have put version
0.94 to hobbes today, so it can probably be found in the incoming or new
directory. The archive name is "black094.zip".
The program requires the emx runtime library, which is also available from
hobbes or ftp-os2.cdrom.com (/pub/os2/unix/emx09a/emxrt.zip).
Changes from version 0.93:
Timer implementation changed to work with pre-Warp OS/2.
Mouse move sensing code changed slightly to overcome the problem with
spurious mousemove events. Result is that the -m switch works more
reliably together with Filebar and some other programs that caused
problems before.
The switch -p was added (compatibility with some more monitors/graphics
adapters).
The switch -n was added (to use Blackout as a minimalistc screen saver
for non-DPMS systems).
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
IBM announces OS/2 Warp Entertainment Toolkit beta
Kit for games, entertainment software developers
AUSTIN, Texas, Oct. 3, 1995...IBM today announced the availability of the
beta version of the OS/2* Warp Entertainment Toolkit on "The Developer
Connection for OS/2, Volume 8" (DevCon8). The beta has been distributed to
the more than 17,000 developers who are members of the Developers Assistance
Program (DAP).
The Toolkit offers new video, audio, joystick, and networking enhancements
from IBM that can help developers create exciting PC entertainment titles for
IBM's OS/2 Warp and build on the existing resources in DevCon. DAP members
receive tools, software technology, and information quarterly on the DevCon
CD-ROM for use in OS/2 Warp development efforts.
"Developers want direct access to devices and cross-platform capabilities,"
said Lloyd Webber, IBM Personal Software Products worldwide games brand
manager. "The OS/2 Warp Entertainment Toolkit gives them those resources for
developing sophisticated interactive PC entertainment for the OS/2 market."
New development tools
The Entertainment Toolkit offers the following capability improvements in
areas ranging from sound and imagery to player interaction:
OS/2 Warp Video offers enhanced software support to OS/2 digital video
and PC entertainment programs through features like Direct Interface
Video Extensions (DIVE) with full-screen support, Direct Access to Video
Buffer and 32-bit Virtual I/O. DIVE, an API in OS/2 Warp, gives OS/2
applications direct access to PC video hardware, enabling developers to
generate the high-speed graphics needed for today's advanced multimedia
software. The DIVE graphics interface allows powerful, high-speed games
and digital video applications to use a single high-speed API for such
useful techniques as stretching (manipulating an image to fit any screen
size), clipping ( reusing a graphic in different areas of an application)
and color conversion (dictating the color palates used in the
application).
OS/2 Warp 3D enables 3D graphics modeling and rendering to ensure maximum
visual performance. IBM integrates the BRender Power Rendering System, a
real-time, 3D graphics software by Argonaut Technologies Ltd., to meet
the speed, size, scalability, flexibility and power requirements of the
most demanding 3D designers.
OS/2 Warp Audio features a direct audio interface that provides a
high-speed audio alternative for applications, such as games, that cannot
afford the more complex methods of synchronizing sound effects with
actions. IBM also provides a musical instrument digital interface (MIDI)
subsystem that produces the advantage of real-time processing of musical
data within the driver itself.
OS/2 Warp Input offers a standard interface for OS/2 PC entertainment
programmers who want to utilize a joystick with their products. OS/2
Warp Input also eliminates the joystick response "flicker" effect seen in
many DOS games running under OS/2.
OS/2 Warp Multiplayer Networking allows developers to write code that
permits multiple players to play together and allows additional players
to join the game in progress. The host computer will ensure that the
visiting player's client is immediately updated with the game's status.
Plus, all clients are informed of the presence of the new player across
the network.
Additional ISV support
Developers can access the OS/2 Warp gaming page at
(http://www.austin.ibm.com/os2games) to receive tools, information and DevCon
updates. Developers also can use the home page to provide feedback and sign
up for free membership in DAP, which provides technical support and assistance
to developers working with OS/2.
The OS/2 Warp Entertainment Toolkit is expected to be complete in the first
quarter of 1996. The entire Toolkit will be available on DevCon and pieces of
it will be available on the OS/2 Warp games home page.
To assist OS/2 developers, IBM also sponsors Solution Partnership Centers
located in San Mateo, Calif. and Waltham, Mass. ISVs using the centers have
access to PC hardware and interaction with other software developers, and
receive technical support throughout the development process in a lab
environment.
Solution developer support of OS/2 Warp is growing. In 1995, 70 software
developers have announced development plans for more than 200 new native OS/2
Warp applications on both Intel and PowerPC platforms, in addition to the
existing 2,500 OS/2 applications currently on the market. Nearly 3 million
copies of OS/2 Warp have been sold since it was launched.
IBM news releases are available on the Internet, via the IBM Home Page at
http://www.ibm.com
The IBM Fax Information Service allows you to receive facsimiles of prior IBM
product press releases. Dial 1-800-IBM-4FAX and enter "99" at the voice menu.
* Indicates trademark or registered trademark of the IBM Corp.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
IBM Pioneers Groupware For Developers
Cutting-edge object repository and software configuration management services
couple to deliver an industry first
SAN JOSE, CA, October 10, 1995 ... Application development teams are getting
connected through a powerful new tool from IBM, TeamConnection*. Combining the
industry's most robust object repository and advanced software configuration
management services, TeamConnection provides a LAN-based client/server
development environment that allows teams to collaborate during each step of
the development cycle.
TeamConnection provides an unprecedented range of capabilities, including
software configuration, version control, and problem tracking, to manage team
development through the entire application development life cycle. From
business modeling and application design through building, deploying and
maintaining an application, developers can share data, objects, and code in a
collaborative work environment.
Ciba-Geigy Ltd., a biological and chemical company with 80,000 employees
worldwide, is among a number of companies that have evaluated TeamConnection.
"TeamConnection will bring a whole new dimension to our application
development efforts," said Patrick Deville, new technologies consultant,
Ciba-Geigy Limited. "It provides our LAN-based development team with the
robust management and library functions that we expect from our mainframe
systems. We are able to eliminate many manual steps through the managed team
development environment provided by TeamConnection, increasing our developer
productivity and maximizing the quality of our applications."
TeamConnection is built on Object Design, Inc.'s ObjectStore** object-oriented
database, which allows the TeamConnection repository to store, with high
performance, both coarse and fine-grained objects, such as data elements and
logic records. ObjectStore supports the information model through which
various development tools can share data and work together to rapidly build
and improve applications.
"TeamConnection creates a collaborative development environment on the LAN,"
said Tim Negris, vice president, sales and marketing, IBM Software Solutions.
"It allows teams to store development objects in the repository on the server
and access and use that information on their client workstations. The ability
to share and reuse development objects significantly boosts productivity and
software quality."
Mr. Negris added that IBM plans to aggressively seek participation from
independent software vendors (ISVs). "With open object interfaces,
TeamConnection is an ideal repository for storing other vendors' tool data,"
he said.
According to Judith Hurwitz, president and CEO of Hurwitz Consulting Group
Inc., TeamConnection represents an important component in effective team
software development. "Choosing a visual development environment is only half
of the solution," said Hurwitz. "You need a deployment strategy for
client/server." TeamConnection server and client functions are available on
OS/2*. Server functions will be extended to AIX* and other UNIX** platforms,
and Windows NT**. Client support will be extended to AIX and other UNIX
platforms, and the Windows** family. In addition, build support is provided
for OS/2 and MVS*, and will be extended to include AIX and other UNIX
platforms, VSE*, OS/400*, and the Windows family.
A number of cross-platform application development tools from IBM are
integrated with TeamConnection, including: VisualGen* V2.0, a client/server
visual application generation tool; VisualAge for C++*, an award-winning
visual development environment for C++; VisualSet for OS/2 COBOL*, a visual,
object-oriented desktop version of COBOL; and PL/I for OS/2*, a desktop
PL/I-based development environment that features a graphical user interface
builder. IBM plans to further enhance the integration of tools to
TeamConnection as new releases of current offerings and new tools become
available.
TeamConnection's set of open Application Programming Interfaces (APIs)
supports the integration of non-IBM tools into the team development
environment, allowing customers to leverage their existing investments.
Today's announcement includes a new ISV program to aggressively jump-start
TeamConnection integration.
Independent Software Vendor Program
TeamConnection can provide a set of services to ISV tools, which will extend
tool capabilities in areas that are key to managing the application
development life cycle. The first of many vendors with leadership technology
expected to incorporate TeamConnection services is Compagnie Generale
d'Informatique (CGI), a worldwide provider of application development software
and services. CGI has integrated PACBASE/CS**, its life-cycle development
environment, with TeamConnection to take advantage of advanced software
configuration management functions.
Vendors interested in extending the value of their tools through integration
with TeamConnection can participate in IBM's vendor enablement program. This
program provides integration assistance to qualified tool vendors.
TeamConnection's Advanced Features
Configuration management support to help identify, organize, manage and
control access to development data. In addition, team members are
notified of changes to development data and alerted when action on their
part is required;
Version control features, which minimize storage requirements and
preserve application versions at critical points in the development
process so that programmers can make modifications while working with a
functioning version of their code;
Integrated build functionality lets teams split development into multiple
parallel tasks, increasing efficiency. Developers can create
applications on one server and have machine-specific versions
automatically built for other processor types across a LAN, dramatically
increasing their productivity;
Packaging and distribution support handles electronic application
distribution across LANs via file server technology such as IBM's NetView
Distribution Manager/2*;
Problem tracking and change control support manages the process of
changing development data, keeping track of what changed, who changed it
and why it was changed -- and associates defects and features with
appropriate changes;
Reporting facility provides the ability to query data and project status;
A backup and recovery facility handles archival storage, and;
Information model provides the integrating platform through which
development tools share data.
TeamConnection for OS/2 Pricing and Availability
TeamConnection for OS/2 is priced at $1999 per user and is available October
24, 1995. For additional information on TeamConnection for OS/2 or the vendor
enablement program, please call 1-800-IBM-3333.
For information via the Internet, users can access the IBM software page at
http://www.software.ibm.com. Then, search on "go TeamConnection." IBM's home
page can be found at http://www.ibm.com.
IBM, the world's largest software provider, creates, develops and manufactures
the industry's most advanced information technologies, including computer
systems, software, networking systems, storage devices and microelectronics.
IBM's Software Solutions Division provides data management, application
development and workgroup solutions for mission-critical applications on PCs,
workstations, LANs and host systems.
* Indicates trademark or registered trademark of International Business
Machines Corporation
** Products or companies mentioned are trademarks or registered trademarks of
their respective holder.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
VisualAge For COBOL For OS/2 Extends COBOL To Your OS/2 Workstation
IBM VisualAge for COBOL for OS/2 revitalizes your COBOL applications by
extending COBOL to your OS/2 workstation
In addition to bringing COBOL to your OS/2 desktop, IBM VisualAge for COBOL
for OS/2:
Offers object-oriented language extensions.
Extends COBOL to a client/server environment.
Increases programmer productivity.
Saves you time and money by taking advantage of the current skill base in
your organization and preserving your current data.
Increases ease-of-use with a variety of development tools.
IBM VisualAge for COBOL for OS/2 is a cost-effective solution that offers the
following enhancements to COBOL.
Object-Oriented Language Extensions:
- Allow COBOL programmers to create objects in a language they already
know, eliminating a long learning curve.
- Offer 32-bit implementation.
- Provide direct-to-SOM implementation.
Client/Server Enablers:
- Run COBOL programs on your OS/2 desktop, while your data remains on
the host.
- Easily access remote data from DB2, CICS, VSAM/SAM MVS files, and
OS/400 Record Files.
- Work with MQSeries for OS/2 using MQSeries Three Tier for OS/2.
- Comply with ISO and ANSI COBOL standards.
Improved Productivity and Ease-of-Use:
- Easily take advantage of these COBOL enhancements with the help of a
rich set of tools.
IBM VisualAge for COBOL for OS/2 is slated to become available in early
November.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Mr. Ed Now Available
Mr.Ed is a multi-window 32-bit shareware text editor for OS/2 PM. Mr.Ed's
functionality is designed to be suitable for any text editing job.
In addition, Mr.Ed provides several features that support writing source code.
Mr.Ed also takes advantage of OS/2 specialities: Drag'n'Drop (files, fonts,
colors), EAs (cursor position, bookmarks), multiple threads, and clipboard
data exchange.
Furthermore, Mr.Ed is not based on the standard MLE control element, so there
is no loss of performance when editing large files.
Featues:
configurable Syntax-Highlighting
configurable third-party Online-Help
configurable context menu
unlimited number of edit windows
"Window Monitor"
pipe-operator support
configuration via commandline
cursor is set to his former editing position when a file is opened
Drag & Drop support
easy to use macro recorder
list of C/C++ functions defined in a source file
jumps to free defineable brackets
persistant bookmarks
line sorting
free defineable keyboard shortcuts
various word functions
configurable print function
word wrap function
automatic recognition of unix-format files
configurable toolbar
and much more...
Mr.Ed is shareware, but fully functional and not "crippled" in any way.
The archive can be downloaded from the following sites:
hobbes.cdrom.com (currently in incoming, proposed directory: /pub/os2/editors)
ftp-os2.nmsu.edu (currently in incoming, proposed directory: /pub/os2/editors)
Filename: mred103e.zip (English version), mred103g.zip (German version)
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Freeware OS/2 Class Library 1.11 Now Available
The new release 1.11 of our freeware OS/2 Class Library (OCL) for OS/2 VIO and
OS/2 PM is now available via CIS (GO OS2INSIDE) and ftp (Hobbes and
ftp.leo.org).
Don't panic! These are really good news for C++ programmers using IBM C-Set++
2.x, VisualAge C++ 3.0, Borland C++ 2.0, Metaware HighC/C++ 3.3x, Watcom C++
10.x and - guess it - gcc/emx 2.7.0!
Yes - the port for gcc/emx is done and working. Thanx to Ralph Paul who did
the job.
There is another major step foreward in OCL 1.11: The notebook bug - annoying
since the first release - has been fixed.
The class OProcStat for complete system reports is now available for all
supported compilers when developing for OS/2 Warp. The library now uses the
new 32bit-API DosQuerySysState. So no thunking is required and OProcStat can
be used with Borland, Metaware and gcc/emx as well.
The reference book has been updated, but it's far from complete. We're
working on this topic.
Hi, gcc-users - give it a try! Please report everything, success or problems,
to the mail address printed in the OCL Reference Book.
You need the following archives:
OCLINST.ZIP - Installation and Maintenance Utility Pack
OCL111.ZIP - OCL 1.11 Release Pack
Users of OCL 1.10 can use the Installation and Maintenance Tools shipped with
this release.
Announcements - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 5. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
How Do I Get EDM/2?
EDM/2 can be obtained in any of the following ways:
On the Internet
All back issues are available via anonymous FTP from the following sites:
- hobbes.nmsu.edu in the /os2/newsltr directory.
- ftp.luth.se in the /pub/os2/programming/newsletter directory.
- generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory.
The EDM/2 mailing list. Send an empty message to edm2-info@knex.mind.org
to receive a file containing (among other things) instructions for
subscribing to EDM/2. This is a UUCP connection, so be patient please.
IBM's external gopher/WWW server in Almaden. The address is
index.almaden.ibm.com and it is in the "Non-IBM-Originated" submenu of
the "OS/2 Information" menu; the URL is
"gopher://index.almaden.ibm.com/1nonibm/os2nonib.70".
On Compuserve
All back issues are available in the OS/2 Developers Forum 2.
IBM Internal
IBM's internal gopher/WWW server in Almaden. The address is
n6tfx.almaden.ibm.com and it is in the "Non-IBM-Originated Files" menu;
the URL is "gopher://n6tfx.almaden.ibm.com/1!!nonibm/nonibm.70".
On BBS's
From BBS's in Denmark, send email to Jesper Nielsen at
afdata@pop02.ny.us.ibm.net for a location near you.
How do I Get EDM/2? - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6. Building an Editor (Part 3) ΓòÉΓòÉΓòÉ
Building an Editor (Part 3)
Written by Eric Slaats and Marc Mittelmeijer
Introduction
In the last two articles in this series we created a small editor based on the
MLE control. We didn't receive as much mail as the previous article, however.
(Maybe because the mail server we are attached to crashed?) So if you sent
mail to us and didn't receive a reply, please send it again. Some of the mail
we received (thanks for the kudo's) mentioned some items worth repeating here.
Memory allocated?
We received some mail from people who had problems recompiling the samples
because the new and delete statements are used. Two things have to be said
about this.
new and delete are C++ functions, so in order to use them, you've got to
use a C++ compiler. If a straight C compiler is used, these statements
are not recognized. If you don't want to use these statements, malloc
and free or the OS/2 API calls DosAllocMem and DosFreeMem may be used.
All these methods should provide you with the amount of memory requested.
The second item is a bug in the way memory is allocated in the EDITOR2
example. It was Graham TerMarsch who brought this to our attention. If
memory is allocated by using new[], it should be freed by using delete[].
This isn't fatal,the program will compile and work just fine. On the
other hand it may cause some erratic behavior. Besides that if only the
pointer is freed, the allocated memory will not be freed! In the
examples included with this article, this bug is corrected. (Thanks
Graham.)
Problems with the resource file!
Some people who tried to recompile the included resource file with RC or other
compilers then the Borland resource compiler got errors. The cause for this
is that the Borland compiler doesn't need the os2.h include in the resource
file. It just assumes it is there. If the line
#include <os2.h>
is added, the resource file will compile just fine.
In this article we will cover how to change the fonts used by the MLE editor,
and a way to save a standard font for the editor. To save font information,
we will use a .INI file.
The button icons are somewhat smaller in the EDITOR3 example. We use a
1280/1024 screen, so the 32x32 buttons don't look obnoxiously large. Included
in the EDITOR3.ZIP file you'll find a set of 28x28 bitmaps for the buttons.
Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6.1. Some Strategy ΓòÉΓòÉΓòÉ
Some Strategy
As mentioned in earlier articles, we think every developer should go the extra
mile to fully implement drag and drop. Of course this also implied fonts.
Unfortunately, the MLE control has a few caveats when it comes to handling
presentation parameters. We will look at a way around them.
What strategy should we take? When it comes to fonts there are an awful lot of
arguments to consider. You only have to look at the FONTMETRICS structure (or
the derived FATTRS structure) to get our point. The questions are: do we need
all this information to change the font in the MLE editor? And what
information do we need to save the currently used font?
One way to change a font in an MLE control is using drag-n-drop. If a font
palette drop is used, something known as a called presentation parameter is
used to change the font. A presentation parameter is actually a simple string
with a description of the parameter in question. Handling a presentation
parameter string is a lot simpler then messing with the FONTMETRICS (or the
FATTRS structure) structure. For the simple things we want to accomplish, the
presentation parameter information is an ideal tool and we'll use that as a
starting point.
We want to be able to change fonts of the editor in two ways:
1. Dropping a font on the MLE.
2. Using the standard font dialog.
If you tried a font drop with the EDITOR2 example you should have found that
this already worked! You should also have found that some of the font
attributes aren't displayed properly! For example, take the outline attribute
on a Times Roman font. You will find that it won't display this font! Maybe
you've also noticed that the font isn't saved when you shut the editor down.
Something to fix these things has to be done.
The font in an MLE control can be changed in two separate ways:
A MLM_SETFONT message can be posted to the control. To do this we need a
FATTRS structure which contains all the necessary font information. (We
will see more about the FATTRS structure in a moment.)
Or, we can use the WinSetPresParam function and set the presentation
parameters for the control. (It is this function the PM uses to
associate a presentation parameter with a window. On other words, this
function is invoked when a font is dropped on the MLE.)
The effect of both methods is the same when looking at the editor
(however, we can only set the font-attributes by using the MLM_SETFONT
message, we can't set them with a drop!)
Note: Both the methods used for setting the font can be undone by the undo
function supplied by the MLE (MLM_UNDO message).
Inside the MLE control though both methods aren't completely compatible. If
the font is set by using a presentation parameter drop, the MLE will process
this drop. If we query the font in use by an MLE after a font drop - using
the MLM_QUERYFONT message - the FATTRS structure returned by the query will
contain the correct values. So the MLE processes a font-drop in such a way
that the dropped font can be queried by MLM_QUERYFONT!
On the other hand if we query the font presentation parameter
(WinQueryPresParam with the presentation parameter PP_FONTNAMESIZE), we get
none or the last font dropped. So the presentation parameter attached to the
control doesn't have to stand for the same font as the control is displaying!
So we should always query the MLE if we want to know what font is in use!
(This may give some trouble if we want to know the point size of a font which
is very easily obtained from a presentation parameter but it's almost
impossible to extract this from a FATTRS structure.)
So what do we need?
A way to capture the font-drop event so the presentation parameter can be
intercepted to fix the attribute problem.
A way to convert the attributes contained in the font presentation
parameter to a FATTRS structure member.
A way to remember the point size of the font in use.
If we've got this, we can build a program which will always show the correct
font, no matter if a presentation parameter is used, or MLM_xxxxxFONT message
is used.
Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6.2. The Standard Font Dialog ΓòÉΓòÉΓòÉ
The Standard Font Dialog
One of the ways to change the font in the MLE control is to invoke the
MLM_SETFONT message. This message sends a FATTRS structure to the MLE. This
structure describes fonts and must be filled with valid values so the MLE can
select the proper font.
The easiest way to obtain these font-values (FATTR structure) is by using the
standard font dialog. Just like the standard file dialog, this dialog was
included in OS/2 2.0 to prevent programmers from making all sorts of dialogs to
change fonts. And just like the standard file dialog it has a ridiculous
number of things to be initialized before it may be used.
To use this dialog a FONTDLG structure has to be initialized before invoking
the dialog.
typedef struct _FONTDLG
{
ULONG cbSize; // Structure size
HPS hpsScreen; // Screen presentation space
HPS hpsPrinter; // Printer presentation space
PSZ pszTitle; // Dialog title string
PSZ pszPreview; // Font-preview window string
PSZ pszPtSizeList; // Application-provided point size list
PFNWP pfnDlgProc; // Custom dialog procedure
PSZ pszFamilyname; // Family name buffer
FIXED fxPointSize; // Point size of the font
ULONG fl; // FNTS_* flags
ULONG flFlags; // FNTF_* flags
ULONG flType; // The selected type bits
ULONG flTypeMask; // Mask of type bits to use
ILONG flStyle; // Selected style bits
ULONG flStyleMask; // Mask of style bits to use
LONG clrFore; // Font foreground color
LONG clrBack; // Font background color
ULONG ulUser; // Application-defined
LONG lReturn; // Return value
LONG lSRC; // System return code
LONG lEmHeight; // Em height
LONG lXHeight; // X height
LONG lExternalLeading; // External leading
HMODULE hMod; // Module for custom dialog resources
FATTRS fAttrs; // Font-attribute structure
SHORT sNominalPointSize; // Font point size
USHORT usWeight; // Font weight
USHORT usWidth; // Font width
SHORT x; // The x-axis dialog position
SHORT y; // The y-axis dialog position
USHORT usDlgId; // Dialog ID
USHORT usFamilyBufLen; // Buffersize
USHORT usReserved; // Reserved
} FONTDLG;
It's hell to fill all these values, so we don't want to fill every member off
this structure if we don't need to do it. Before we can use the font dialog,
we fill every item with a NULL value; then we fill the members that are
essential for the handling of the font dialog.
The following members are absolutely necessary to use the font dialog.
FontDlg.cbSize = sizeof(FONTDLG); // Set cbsize (Mandatory)
FontDlg.pszFamilyname = szCurrentFont; // Buffer for fontname (previously defined)
FontDlg.usFamilyBufLen = FACESIZE; // Size fontname buffer
FontDlg.clrFore = CLR_NEUTRAL; // Foreground color for sample
FontDlg.clrBack = CLR_DEFAULT; // Background color for sample
To show that with only these values we can make a font dialog work, a FONTDLG
example is included in the file EDITOR3.ZIP. FONTDLG.ZIP contains the complete
working code for this example.
Treating the font dialog this way in an editor isn't rather user friendly.
Usually we want the font dialog to display the font currently in use, including
the font size and the attributes (underline etc.). To obtain this information
at least one other member of the FONTDLG structure has to be filled. This is
the field containing the FATTRS structure. This structure contains the most
important font information and is also used by the MLE control. A filled
FATTRS structure containing the information about the font currently in use can
be retrieved from the MLE using the MLM_QUERYFONT message.
It would be nice if this is enough to initialize the font dialog. Well, it is.
We can set the fl field off the FONTDLG structure and the fontdialog will set
itself up according to the values contained in the fAttrs field.
FontDlg.fl = FNTS_INITFROMFATTRS; // Init FontDialog from FATTRS
WinSendMsg(hwndMLE, MLM_QUERYFONT, &FontDlg.fAttrs, 0L);// Retrieve font values from MLE
For now we have enough to build the function that can be incorporated in the
editor. Only a few details have to be taken care off. Before we start we have
to set all the values of the FONTDLG structure to NULL. Besides that we want
the values set by the dialog to be remembered so that the next time the dialog
is invoked the proper values (e.g. point size) will show. We can achieve both
by declaring the FONTDLG variable static. If a variable is declared as a
static, its contents will be remembered until the next time the function in
which it is declared is called again. Besides that, static initializes the
variable with NULL values.
The new function to change the fonts in the MLE editor will look something like
this.
case IDM_CHANGEFONT:
{
char szCurrentFont[FACESIZE]; // Setup fontname buffer
static FONTDLG FontDlg; // values FILEDLG set to 0
FontDlg.cbSize = sizeof(FONTDLG); // Set cbsize (Mandatory)
FontDlg.fl = FNTS_INITFROMFATTRS; // Init from FATTRS
FontDlg.usFamilyBufLen = FACESIZE; // Size fontname buffer
FontDlg.pszFamilyname = szCurrentFont; // Fontname buffer
FontDlg.clrFore = CLR_NEUTRAL; // Foreground color for sample
FontDlg.clrBack = CLR_DEFAULT; // Background color for sample
WinSendMsg(hwndMLE, MLM_QUERYFONT, &FontDlg.fAttrs, 0L);// Retrieve font values
WinFontDlg(HWND_DESKTOP, hwnd, &FontDlg); // Start font dialog
if (FontDlg.lReturn == DID_OK) // OK pressed ?
WinSendMsg(hwndMLE, // Activate new font
MLM_SETFONT,
&FontDlg.fAttrs,
NULL);
}
break;
If we use it the first time, the default font for the MLE will be displayed.
Every time the font dialog is invoked, the last font used is displayed,
including the attributes and the point size used (remembered in the static
FONTDLG structure).
Because this is a small and elegant solution, something has to go wrong, and
indeed something does. We want the editor to incorporate every goody OS/2 has
to offer, so dropping a font on the MLE window should result in a font change.
If we try this it seems to work just fine. However there are a few situations
where things go wrong.
1. If a font without further attributes (underline, outline, strikeout) is
dropped, the MLE takes over the dropped font and it can be queried
correctly. If the font dialog is opened the right font will show;
however, the font size won't be correct. The dialog will show the last
font size used! So we have to find a way to restore the correct font
size in the FONTDLG structure which is used for setting up the
fontdialog.
Apparently the WinFontDlg() function cannot determine the point size from
the FATTRS structure (well, neither can we).
2. If a font with attributes is dropped on the MLE the attributes won't
show. It isn't that the MLE control isn't capable of showing these
attributes; it just won't show them if dropped in the form of a
presentation parameter.
So if we want to support complete font dropping, we've got to do something
about this. To accomplish this we have to capture a font drop.
Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6.3. Detecting the Font Presentation Parameter ΓòÉΓòÉΓòÉ
Detecting the Font Presentation Parameter
What's a presentation parameter?
A presentation parameter is a character string that represents certain
presentation values such as color- and font- values. These values can be used
when displaying a window. If we drop a font on the titlebar of a window, the
titlebar (also a window) will show that font. The same thing happens with
colors.
Note: Although OS/2 supports most of the presentation parameters for the
standard controls in most cases, there are some points when things aren't
completely supported. An example of this is the font drop on an MLE. Another
example is a color drop on an MLE. (A MLE excepts only indexed colors.) Also,
not all OS/2 applications support presentation parameters; the application has
to be utilized to do so!
For this article we are only interested in the PP_FONTNAMESIZE presentation
parameter. The drop of this presentation parameter is what we want to take
actions upon. If this presentation parameter is queried from the MLE, a string
is retrieved that looks something like this:
pointsize.facename.attr1.attr2.attr3
This structure is always used by PP_FONTNAMESIZE to describe a font. The items
in this string are separated by a dot (.). Only the first two items are
mandatory. So the following examples are valid presentation parameter strings.
"8.Helv"
"18.Courier Bold"
"24.Times New Roman Bold Italic"
"12.System Proportional"
There are five possible attributes a font can have,although only three of them
are supported by the standard font dialog and by the FONTDROP dialog. The
attributes bold and italic are normally supported by the font style, so they
are omitted in the font dialog. However these attributes can still be used.
If we use bold on a already bold font it gets wider. If we use italic on a
already italic font, the font gets italicized more.
These are the five possible font attributes:
Italic
Outline
Strikeout
Underscore
Bold
So the following presentation parameter strings are also valid:
"8.Helv.Outline"
"18.Courier Bold.Bold"
"24.Times New Roman Bold Italic.Italic.Underscore.Bold"
"12.System Proportional.Strikeout"
Now we know how a presentation parameter looks and what the possible values
are, we've only got to capture a fontdrop to fix the two points mentioned in
the previous section.
Besides that we've learned another thing. There aren't three but five font
attributes. The attributes bold and italic can't be accessed through the
standard font dialog or by the font palette. Let's take a small detour and
find out how we can use these attributes in our MLE editor.
Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6.4. Applying the Bold and Italic Attributes ΓòÉΓòÉΓòÉ
Applying the Bold and Italic Attributes
We can set and query the current font in the MLE by using the MLM_SETFONT and
MLM_QUERYFONT messages. By using these messages, we can build two very simple
functions that will enable us to change the contents of a MLE to bold or to
italic.
Before we look into these functions, lets take a look at the fsSelection field
of the FATTRS structure. This field contains the font attributes. If this
field contains a 0, no attributes are attached to the font. The following
values can be or'd together to make a valid entry for fsSelection.
FATTRS_SEL_ITALIC
FATTRS_SEL_UNDERSCORE
FATTRS_SEL_BOLD
FATTRS_SEL_STRIKEOUT
FATTRS_SEL_OUTLINE
We're only interested in the bold and italic attributes because the rest can
be set through a font drop or by invoking the font dialog.
To change the font to bold or italic, two new entries are added to the edit
menu: bold and italic. We want these to be toggle entries. (Yeah yeah we
know a checkmark in the menu should be in place.) If one of these menu
options is chosen, the font in the MLE must add the attribute if it isn't
there or delete the attribute if it is there. To accomplish this we'll use
the XOR oparator (^).
The code example to toggle the bold attribute for the current font looks like
this:
case IDM_BOLD:
{
FATTRS fAttrs;
WinSendMsg( hwndMLE, MLM_QUERYFONT, &fAttrs, NULL ); // Query font
fAttrs.fsSelection ^= FATTR_SEL_BOLD; // XOR with bold attribute
WinSendMsg( hwndMLE, MLM_SETFONT, &fAttrs, NULL ); // Set font
}
break;
This is the end of the detour. Let's get back to the article.
Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6.5. Capturing a Font Drop ΓòÉΓòÉΓòÉ
Capturing a Font Drop
What happens if a presentation parameter (font, color or scheme) is dropped on
a window, and why do we want to capture this event?
We want to capture this event for two reasons (as mentioned in the section
about the standard font dialog).
1. It is very hard to determine the font's point size from the FATTRS value
as used by the MLE. If we set a font by using the font dialog, the point
size set can be remembered. If a font drop occurs, the point size of the
dropped font may differ from the point size remembered in the FONTDLG
structure. So by the next call of the Font dialog we've got a problem.
However, the point size can easily be derived from a presentation
parameter. So, we want to extract the point size from the dropped font
presentation parameter and store it in the FONTDLG structure.
2. A font drop with fonts that has attributes attached isn't processed
properly by the MLE. By capturing a font drop we can check on the
attributes of the dropped font and set them according to the dropped
font.
To build a solution for both problems we need the presentation parameter
string of the dropped font. Let's see how we can obtain the string that
describes the dropped font.
If a presentation parameter drop is performed, a WM_PRESPARAMCHANGED message
is sent to the window the drop is performed upon. (This message also occurs
if the presentation parameters are set using the WinSetPresParam function, or
if the presentation paramaters are inherited.)
If this message is send, the first parameter of the WM_PRESPARAMCHANGED
message contains the type of presentation parameter dropped. There are quite
a lot (29 to be exact) of presentation parameters but in this case we're only
interested in the PP_FONTNAMESIZE attribute (font name and size attribute).
In our case we have to intercept the WM_PRESPARAMCHANGED message in the MLE
window standard procedure. This means subclassing the MLE window.
Fortunately, we've already done this to process file drops (see EDM/2 3-6)! So
we only have to add another case for WM_PRESPARAMCHANGED.
If a WM_PRESPARAMCHANGED occurs we can query the presentation parameters of a
window by calling the WinQueryPresParam function. This function enables us to
query a presentation parameter string. In our case we want to query the
PP_FONTNAMESIZE parameter. The WinQueryPresParam function is rather complex;
it looks like this:
WinQueryPresParam(hwnd, // Window handle
idAttrType1, // Pres param attribute 1
idAttrType2, // Pres param attribute 2
pidAttrTypeFound, // Attrib ID found
cbAttrValueLen, // Size of found attribute
pAttrValue, // Found attribute value
flOptions); // Flags
This function takes two presentation parameter attributes. It will search for
the second presentation parameter if the first one isn't found. Since we only
act upon a WM_PRESPARAMCHANGED with the first parameter set to
PP_FONTSIZENAME, we are sure a presentation parameter is present. This means
we can ignore the second presentation parameter value in this function.
The only other parameter of this function that we can use is the flOptions
parameter. With the flags in this field we can control the query in such a
way that we don't query the inherited presentation parameter values from
owners, but the value in the queried window (the MLE window in our case). To
do this we have to fill flOptions with the QPF_NOINHERIT value.
If we capture the presentation parameter string dropped on the MLE, what
actions do we have to take?
Well first we've got to send the WM_PRESPARAMCHNAGED message to the original
MLE window procedure to make sure the presentation parameter is processed so
that the correct font value is attached to the MLE and will appear in the
FATTRS structure if we query the MLE.
The original MLE window procedure is queried at the start of the subclass (see
EDM2-6).
A short reminder: the pointer to the original MLE window procedure is stored
in the window word attached to the MLE. This window word is retrieved at the
start of the MLE subclass. So the following code makes the original
MLE-window procedure available.
PFNWP oldMLEProc;
oldMLEProc = (PFNWP) WinQueryWindowULong(hwnd, QWL_USER); // Get Winproc pointer from winword
Now that the pointer to the original window procedure is known, we can call
this procedure with the passed parameters to make sure the drop is processed
by the MLE.
What's next? Let's take the problems one at the time. First we'll define a
way to extract the point size from the dropped font and store it in the
FONTDLG structure so the right point size will show if we invoke the font
dialog. This has a rather ugly penalty. If we want to keep the point size of
the used font in the FONTDLG structure, we have to make this variable public.
Otherwise it can't be accessed in the MLE subclass as in the mormal window
procedure. We will still use static in the definition because that will
insure that the values in the structure will be set to NULL.
The entry in the MLE subclass may look like this if we fix the point size
problem.
case WM_PRESPARAMCHANGED:
{
if ((ULONG)mpParm1 == PP_FONTNAMESIZE)
{
oldMLEProc(hwndMLE, msg, mpParm1, mpParm2); // Call original MLE procedure
CHAR PPAttrValue[FACESIZE+64]; // PP string buffer
WinQueryPresParam(hwndMLE, // Query dropped font
PP_FONTNAMESIZE,
0,
NULL,
FACESIZE+64,
&PPAttrValue,
QPF_NOINHERIT);
//----------------------------------------------------------------------------
// set point size in FontDlg
//----------------------------------------------------------------------------
char String[3];
FontDlg.fxPointSize = (atoi(strncpy(String,
PPAttrValue,
((ULONG)strchr(PPAttrValue,'.') -
(ULONG)PPAttrValue)
) ) ) << 16;
return(0);
}
}
break;
The first part of this code sample shouldn't contain any surprises. The
second part however is something different. It's a strange brew of all sorts
of string functions. (To use these string functions, we've got to include
string.h in the file.)
We want to retrieve the point size from the presentation parameter string. The
point size is represented by all the characters before the first occurence of
a dot (.). So the first thing we do is extract the characters before the dot,
so we have a string that contains the point size in text. To achieve this, we
first query the position of the dot in presentation parameter string by using
the strchr function. This function returns a pointer to a substring in the
presentation parameter string that starts with the dot. If we subtract the
pointer to the presentation parameter string from this value we get the number
of characters at the beginning of the presentation parameter string that
contain the point size.
(ULONG)strchr(PPAttrValue,'.') - (ULONG)PPAttrValue)
Next the number of characters returned from the above function are copied in a
string from where it can be converted into a number. The strncpy can be used
to copy a certain number of characters from the beginning of a string to a
destination string. We can be fairly sure that the point size won't exceed
999, so a character string with length 3 should be enough to contain the point
size.
char String[3];
strncpy(String, PPAttrValue,((ULONG)strchr(PPAttrValue,'.')-(ULONG)PPAttrValue));
The next step is to convert the contents of the variable String to an integer.
This can be done immediately because the strncpy returns the pointer to
String. The function normaly used to convert an ASCII string to an integer is
the atoi function.
However, the normal point size isn't the value we can put into a fxPointSize
field of a FONTDLG structure. The fxPointsize field is of the FIXED type,
which is a signed integer fraction (16:16). This means we've got to multiply
the point size value we found by 65536 (2^16). An easier way to accomplish
this is to perform a 16 bit shift to the left (<< 16).
This leads to the following construction:
FontDlg.fxPointSize = (atoi(strncpy(String,
PPAttrValue,
((ULONG)strchr(PPAttrValue,'.') -
(ULONG)PPAttrValue)
) ) ) << 16;
This takes care of the first problem, now the second one, the fontattributes
that aren't set by a drop.
First we've got to check if one of the attributes is set in the presentation
parameter string. Before we can do this, we've got to know how these
attributes are represented in the the presentation parameter string. In one
of the previous sections we've seen that the attributes are appended to the
presentation parameter string (dot separated). In the presentation parameter
string the attributes are set by the following text strings:
Italic, Outline, Strikeout, Underscore, Bold
The strstr function can be used to check if a string appears as a substring in
another string. So this function is used to check for every attribute if it
appears in the presentation parameter string, for example for the Italic
attribute:
if (strstr(PPAttrValue, ".Italic"))
If a attribute is found, we've got to set this in the fsSelection field of the
FATTRS structure so the font can be manually set by a MLM_SETFONT.
As we saw in a previous section, there are five different font attributes.
They are represented by the following five values:
FATTRS_SEL_ITALIC
FATTRS_SEL_UNDERSCORE
FATTRS_SEL_BOLD
FATTRS_SEL_STRIKEOUT
FATTRS_SEL_OUTLINE
Knowing this we can build a valid value for fsSelection by checking on every
attribute and adding these to the fsSelection.
short usfsSelection = 0;
if (strstr(PPAttrValue, ".Italic"))
usfsSelection = usfsSelection + FATTR_SEL_ITALIC;
if (strstr(PPAttrValue, ".Outline"))
usfsSelection = usfsSelection + FATTR_SEL_OUTLINE;
if (strstr(PPAttrValue, ".Strikeout"))
usfsSelection = usfsSelection + FATTR_SEL_STRIKEOUT;
if (strstr(PPAttrValue, ".Underscore"))
usfsSelection = usfsSelection + FATTR_SEL_UNDERSCORE;
if (strstr(PPAttrValue, ".Bold"))
usfsSelection = usfsSelection + FATTR_SEL_BOLD;
If one of these attributes has been detected, the usfsSelection has a value
greater then 0 so we can simply check it with an if-statement. Next we query
the font currently active in the MLE, (this should be the font dropped, the
call to oldMLEproc has set the current font.) and change the fsSelection in
the FATTRS structure.
if (usfsSelection)
{
FATTRS fAttrs;
WinSendMsg( hwnd, MLM_QUERYFONT, &fAttrs, NULL );
fAttrs.fsSelection = usfsSelection;
WinSendMsg( hwnd, MLM_SETFONT, & fAttrs, NULL );
}
This approach has one flaw: if a font with attributes is dropped, the font
change can't be undone by the undo function. This is because the font is
changed twice. Once by the drop and once by the attributes set. So if a undo
is invoked, only the attributes set will be undone.
The complete code for the WM_PRESPARAMCHANGED message:
case WM_PRESPARAMCHANGED:
{
if ((ULONG)mpParm1 == PP_FONTNAMESIZE)
{
oldMLEProc(hwndMLE, msg, mpParm1, mpParm2);
CHAR PPAttrValue[FACESIZE+64];
WinQueryPresParam(hwndMLE,
PP_FONTNAMESIZE,
0,
NULL,
FACESIZE+64,
&PPAttrValue,
QPF_NOINHERIT);
//----------------------------------------------------------------------------
// set pointsize in FontDlg
//----------------------------------------------------------------------------
char String[3];
FontDlg.fxPointSize = (atoi(strncpy(String,
PPAttrValue,
((ULONG)strchr(PPAttrValue,'.') -
(ULONG)PPAttrValue)
) ) ) << 16;
//----------------------------------------------------------------------------
// set attributes in MLE and in FontDlg FATTRS]
//----------------------------------------------------------------------------
short usfsSelection = 0;
if (strstr(PPAttrValue, ".Italic"))
usfsSelection = usfsSelection + FATTR_SEL_ITALIC;
if (strstr(PPAttrValue, ".Outline"))
usfsSelection = usfsSelection + FATTR_SEL_OUTLINE;
if (strstr(PPAttrValue, ".Strikeout"))
usfsSelection = usfsSelection + FATTR_SEL_STRIKEOUT;
if (strstr(PPAttrValue, ".Underscore"))
usfsSelection = usfsSelection + FATTR_SEL_UNDERSCORE;
if (strstr(PPAttrValue, ".Bold"))
usfsSelection = usfsSelection + FATTR_SEL_BOLD;
if (usfsSelection)
{
FATTRS fAttrs;
WinSendMsg( hwnd, MLM_QUERYFONT, &fAttrs, NULL );
fAttrs.fsSelection = usfsSelection;
WinSendMsg( hwnd, MLM_SETFONT, & fAttrs, NULL );
}
return(0);
}
}
break;
Building an Editor ( Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6.6. Saving information in OS2.INI ΓòÉΓòÉΓòÉ
Saving information in OS2.INI
It's a pain, constantly having to change the font settings if an application is
started. So let's have some more fun with the MLE and look at an easy way to
save the font information used in the MLE editor. The method described here
will only be used to save font information in the OS2.INI file so the last font
used in the editor will automatically be loaded as the editor is started again.
However, roughly the same method is used in the SMALLED application to save
font information in the extended attributes of text files. This way font
information can be stored with a file while this information isn't stored in
the file!
When we're at it, we'll take a small detour and take a look at how the window
size and position can be saved in the OS2.INI.
Most applications will have to save some general information at one time or
another. In the old DOS days this kind of information was stored in a setup
file which was read when the application was started. The problem with these
kind of files was that every developer invented the wheel again and took his
own approach. When OS/2 came along a structured method for storing this kind
of information was provided in the profile API. Through the profile function
calls a programmer can create a private profile for an application or store
information in the OS/2.INI file.
The OS2.INI file is a general profile for applications under OS/2. This file
is read at boot time and is available in memory, so fast access is insured.
The OS/2 profile files (INI files) are stored in a binary format and are
accessable in a sort off database like fashion. The general form in which data
is stored in a profile looks has a three level layout.
Application name
Key name
Key Data
Key name
Key data
:
:
Key name
Key data
Application name
:
:
In a INI file more application names can be present. Under every application
data can be stored under a key name. The form for this data is free. It can
be a long, a character string, a structure etc. as long as it doesn't exceed
the 64 Kb limit.
Now we know that data can be stored and retrieved (we will see exactly how in a
minute) in any form we like, we have to find a convenient way to store font
data.
We have two options: we can save the font information as a FATTRS structure or
to save it as presentation parameter information. The FATTRS structure has as
disadvantage that we can't save the point size. To cope with this a
FONTMETRICS structure has to be used. This is a bad case off overkill for the
simple effect we want to achieve. Using presentation parameter information has
the advantage that we've already got a routine process this information. So a
call to WinSetPresParam is enough. The first step in saving font information
is building a function that can build a presentation parameter string from the
FATTRS information that can be retrieved from the MLE and the point size
information from the FONTDLG structure. The information about how a
presentation parameter string looks can be found in the section Desecting the
Font presentation parameter.
Filling a string with values is rather easy, we can simply use the sprintf
statement.
// FontDlg == Global
CHAR PPAttrValue[FACESIZE+64]; // PP string
FATTRS fAttrs; // Font information
WinSendMsg( hwndMLE, MLM_QUERYFONT, &fAttrs, NULL ); // Query current font
sprintf(PPAttrValue, "%d.%s", FontDlg.fxPointSize >> 16, fAttrs.szFacename);
This code sample isn't too hard. The only thing we've got to take note off are
the dots used in the presentation parameter and the right shift of the
fxPointsize value to obtain a valid point size.
There is still one thing missing from the presentation parameter string
composed in this way: this is the font attributes (if used). To find out if
an attribute is used in a font we conduct bitwise and on the fAttrs.fsSelection
value with all the possible attribute values. If an attribute is found we
simply add it to ppAttrValue. The code to achieve this looks like this:
if (fAttrs.fsSelection & FATTR_SEL_ITALIC)
strcat(PPAttrValue,".Italic");
if (fAttrs.fsSelection & FATTR_SEL_OUTLINE)
strcat(PPAttrValue,".Outline");
if (fAttrs.fsSelection & FATTR_SEL_STRIKEOUT)
strcat(PPAttrValue,".Strikeout");
if (fAttrs.fsSelection & FATTR_SEL_UNDERSCORE)
strcat(PPAttrValue,".Underscore");
if (fAttrs.fsSelection & FATTR_SEL_BOLD)
strcat(PPAttrValue,".Bold");
Now that we have a way to build a presentation parameter string from the
available font information, let's take a look at how we can save this
information in the OS/2 INI file. Before we talk code we have to find a
convenient place in the program flow where we can perform this save. In
moments like this you really come to love OS/2. It has a message
WM_SAVEAPPLICATION message that is sent when the application is about to shut
down. We want to save the font information at shutdown time, so this message
is all we need.
Note: Make sure that the WinDefWindowProc is called after you process this
message!
There are two functions that can be used to write data to a profile:
PrfWriteProfileData for binary data and PrfWriteProfileString for a character
string, which is what we're interested in. The syntax looks like this:
HINI hini; // Initialization-file handle
PSZ pszApp; // Application name
PSZ pszKey; // Key name
PSZ pszData; // Text string
BOOL fSuccess; // Success indicator
fSuccess = PrfWriteProfileString(hini,
pszApp,
pszKey,
pszData);
For HINI we got to obtain initialization handle if we want to use a private
profile. However if we are using the OS2.INI file we can use a predefined
handle, HINI_USERPROFILE.
To fill the pszApp and the pszKey values, it is good practice to add defines in
the header file. So you can be sure that the same entries are used for storing
as well as receiving data.
//----------------------------------------------
// In editor3.h
//----------------------------------------------
#define SAVE_NAME "EDITOR3"
#define PPFONT "PPFONT"
//----------------------------------------------
// During WM_SAVEAPPLICATION
//----------------------------------------------
PrfWriteProfileString(HINI_USERPROFILE,
SAVE_NAME,
PPFONT,
PPAttrValue);
I promised another small detour. Here it is. The most common action to take
at WM_SAVEAPPLICATION is to save the current window size and place. It's done
so often that a special function has been provided. This is the
WinStoreWindowPos function. A nice spin-off of this function is that it will
save the presentation parameter parameters of the frame-window and all it's
(added) controls. So if we change the color of the toolbar or the font used in
the statusbar, it will be remembered!
The WinStoreWindowPos takes the handle of the window to save as a parameter, as
well as the application name and the keyname under which this information must
be saved. Knowing this we can finaly write the compete code for the
WM_SAVEAPPLICATION message.
case WM_SAVEAPPLICATION:
{
CHAR PPAttrValue[FACESIZE+64]; // PP string
FATTRS fAttrs; // Font information
WinSendMsg( hwndMLE, MLM_QUERYFONT, &fAttrs, NULL ); // Query current font
sprintf(PPAttrValue, // Fill PP string
"%d.%s",
FontDlg.fxPointSize >> 16,
fAttrs.szFacename);
if (fAttrs.fsSelection & FATTR_SEL_ITALIC) // Check on Italic attribute
strcat(PPAttrValue,".Italic"); //
if (fAttrs.fsSelection & FATTR_SEL_OUTLINE) // Check on Outline attribute
strcat(PPAttrValue,".Outline"); //
if (fAttrs.fsSelection & FATTR_SEL_STRIKEOUT) // Check on Strikeout attribute
strcat(PPAttrValue,".Strikeout"); //
if (fAttrs.fsSelection & FATTR_SEL_UNDERSCORE) // Check on Underscore attribute
strcat(PPAttrValue,".Underscore"); //
if (fAttrs.fsSelection & FATTR_SEL_BOLD) // Check on Bold attribute
strcat(PPAttrValue,".Bold");
PrfWriteProfileString(HINI_USERPROFILE, // Save font PP in OS2.INI
SAVE_NAME,
PPFONT,
PPAttrValue);
WinStoreWindowPos(SAVE_NAME, // Save window size and position
SAVE_WINPOS,
WinQueryWindow(hwnd,QW_PARENT));// Query frame handle
}
break;
Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6.7. Retrieving Font Information from OS2.INI ΓòÉΓòÉΓòÉ
Retrieving Font Information from OS2.INI
Saving the font and size/position information is one thing, we also need to
retrieve this information the moment the editor is started.
The size/position information has to be loaded after the window is started, but
before it becomes visible. Also the MLE window and the statusbar window must
be created because they participate in the WM_FORMAT and the WM_SIZE message.
The font information must be handled in the same fashion. It must be loaded
after the MLE window is loaded, but before any file information is shown (for
example a file drop on the editor icon).
Normaly this kind of action would be handled during the WM_CREATE message.
However in this case the MLE doesn't exist during the WM_CREATE. In EDITOR2 we
have chosen to create the MLE window directly after the main frame window. The
WM_CREATE message is send by the creation of the frame window, so this isn't a
good spot.
The ideal spot, in our opinion, is right after the toolbar is loaded.
To restore the window size and place (and the presentation parameter attached
to all it's controls) we use the WinSetWindowPos function. This function will
look in the OS2.INI file for a given application and key name and restore the
information previously saved by a WinStoreWindowPos call.
WinRestoreWindowPos(SAVE_NAME,
SAVE_WINPOS,
hwndFrame);
Making the call just like this isn't enough. If WinRestoreWinPos does find the
stored information in the INI file, it applies it to the window identified by
hwndFrame. It doesn't show the window or activate it. To accomplish this we
have to make another call. The WinSetWindowPos function (a very nice function
to know about) can be used to make the window visible, activate the window and
place it on top of the z-order.
We know if the WinRestoreWinPos function had been succesfull if it returns a
TRUE. If it didn't retrieve any information from the OS2.INI file (for example
during the first time editor3 is started) we have to set the size and place
ourselves. The following piece of code will take care of business.
//---------------------------------------------------------------------------------------------
// Set Main window (Frame) size and position
//---------------------------------------------------------------------------------------------
if (WinRestoreWindowPos(SAVE_NAME, // Get and set size en place from OS2.INI
SAVE_WINPOS, //
hwndFrame)) //
WinSetWindowPos(hwndFrame, // Activate window
HWND_TOP, //
0,0,0,0, // (PM will position through WinRestoreWondowPos)
SWP_ACTIVATE | // Activate window
SWP_SHOW); // Show Window else
WinSetWindowPos(hwndFrame, // If no entry in OS2.INI
NULLHANDLE, // default position 10,10
10,10,600,400, // with SIZE 600,400
SWP_ACTIVATE|SWP_MOVE| //
SWP_SIZE |SWP_SHOW); //
For setting the font information we have to use another function. We saved the
font information by calling the PrfWriteProfileString function. This
information can be retrieved by calling the counterpart of this function, the
PrfQueryProfileString. This function will look into the OS2.INI file for the
given application and key, if it doesn't find it, it will return a default
value.
HINI hini; // Initialization-file handle
PSZ pszApp; // Application name
PSZ pszKey; // Key name
PSZ pszDefault; // Default string
PVOID pBuffer; // Profile string
ULONG cchBufferMax; // Maximum string length
ULONG pulLength; // String length returned
pulLength = PrfQueryProfileString(hini,
pszApp,
pszKey,
pszDefault,
pBuffer,
cchBufferMax);
For the default value we can define a presentation parameter string that
contains the standard system font.
"12.System Proportional"
If no value is found, the MLE is set to the default system font. Once a value
is retrieved we've got to set it. To set a font through a presentation
parameter we've got to use the WinSetPresParam function.
HWND hwnd; // Window handle (MLE handle)
ULONG idAttrType; // Attribute type identity (PP_FONTNAMESIZE)
ULONG cbAttrValueLen; // Byte count of the data passed in the pAttrValue parameter
PVOID pAttrValue; // Attribute value
BOOL fSuccess; // Success indicator
fSuccess = WinSetPresParam(hwnd,
idAttrType,
cbAttrValueLen,
pAttrValue);
The beauty of using this function is that it will automatically invoke the
WM_PRESPARAMCHANGED message. So all the right moves will be made to initiate
the point size value in the FontDlg variable and set the fAttrs value in the
MLE control. Even previously set bold and italic attributes will be handled
correctly.
//---------------------------------------------------------------------------------------------
// Set font from the value in OS2.INI
//---------------------------------------------------------------------------------------------
char PPAttrValue[FACESIZE+64];
PrfQueryProfileString(HINI_USERPROFILE,
(PSZ) SAVE_NAME,
(PSZ) PPFONT,
(PSZ) "12.System Proportional",
(PVOID) PPAttrValue,
(ULONG) FACESIZE+64);
WinSetPresParam(hwndMLE, PP_FONTNAMESIZE, strlen(PPAttrValue)+1, PPAttrValue);
Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 6.8. Concluding notes ΓòÉΓòÉΓòÉ
Concluding notes
This is the third (and probably the last) article in a describing a way to
build a small fast editor that can easily be embedded in another application.
We know it isn't complete yet. For example, search and replace is a serious
omission. We hope the articles will be useful for your own program
development. (We received some mail stating so [grin] .) The articles about
the MLE editor are for a large part based on the SMALLED application. This
application is available as share/freeware on the Hobbes ftp site. Currently
it's at version 0.96 and can be retrieved as SMALED96.ZIP.
The EDITOR3 program can be made somewhat simpler if you use the easy toolbar
described in EDM3-8 'Easy Buttonbars'. Besides that I (Eric) am planning
another article based on easy buttonbars to add bubble help to a buttonbar.
Bubble help is a popup window under the buttonbar containing help info about a
button if you mouse over it. So further enhancement based on what we've
written for EDM/2 is possible.
Feel free to use the code any way you like and send us your comments.
The examples are all build and compiled with Borland C++ 2.0.
Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 7. C++ Compiler Review (Part 3) ΓòÉΓòÉΓòÉ
C++ Compiler Review
Written by Gordon Zeglinski
There were a few typos in the C/C++ compiler review benchmark tables presented
in the last issue. Revised tables including the results of the Watcom 10.5
benchmarks will be included in this issue. Watcom 10.5 benchmarks you ask? Yes
due to the number of questions I have gotten about Watcom 10.5, in this issue,
we will look at what's new in Watcom version 10.5.
C++ Compiler Review - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 7.1. What's new in Watcom C/C++ 10.5? ΓòÉΓòÉΓòÉ
What's new in Watcom C/C++ 10.5?
According to the registration card, anyone registering version 10.5 will be
mailed a copy of Watcom 10.6. 10.6 will offer more Win95 support (yuck :>).
Features that are different or are not found in version 10 are considered to be
new.
For the OS/2 programmer, 10.5 features better warp support. The debugger and
sampler (used in profiling code) run better under Warp than their 10a
counterparts. Although they still have problems dealing with multi-threaded PM
programs. Remote debugging of OS/2, Win NT/95 through tcp/ip is now possible.
For those doing 16 bit OS/2 programming the OS/2 1.x toolkit is now included as
well. This compiler can now be used to generate tcp/ip applications.
For the Windows programmer, Win95 support has been added. Also, the NT 3.5
toolkit is included. MFC 3.0 support and a new visual programmer have been
added. The visual programmer is used to build MFC applications. The editor now
includes source revision control hooks.
Improvements of a general nature include a new install program, native C++
exception handling, the ability to browse C code, and better compatibility with
the Microsoft compiler.
Although the sampler and profiler are not new. It is new that they run under
Warp. So we'll take a peek at what the sampler/profiler have to offer.
The profiler displays info about time usage in various levels of detail. The
highest level displays the usage based upon compilation unit. The next level
displays the time usage for functions in a particular module. Finally, the
third level displays the time usage for the lines of a particular function. The
lack of thread specific support severely limits the use of the profiler in any
multi-threaded OS.
C++ Compiler Review - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 7.2. Benchmarks ΓòÉΓòÉΓòÉ
Benchmarks
To allow easy comparison, the complete set of benchmark tables will be included
here with Watcom 10.5 added. Note: the Watcom seive time reported in the last
issue was incorrect.
The following table shows the results of the C benchmarks:
Compiler bsort sieve dhry21 whetstone(S) whetstone(D) Rolled Rolled Unrolled Unrolled
Linpack(S) Linpack(D) Linpack(S) Linpack(D)
Metaware 2.468 4.218 62500.0 142857 111111 3135 2194 3135 2312
VAC++ 2.219 3.750 58139.5 34482 34482 2928 1996 2928 2090
Watcom 1.970 4.090 65789.5 111111 76923 2922 1990 3121 2328
Wat 10.5 2.190 4.25 54347.8 90909 125000 2591 2081 3121 2215
Borland 2.406 6.062 32467.5 17241 17241 2444 1758 2586 1829
The units for the C benchmarks are as follows. Bsort and Sieve are in seconds
(the smaller the number the better). Dryh21 is in Dhrystones/sec. The two
whetstone tests are in KWhets/sec. All the Linpack tests are in KFlops. Except
for the first two benchmarks, larger numbers are better.
Watcom 10.5 performed both better and worse than Watcom 10a in the C benchmark
suit. Overall it performed somewhat worse than version 10a.
The following table show the results of the C++ benchmark.
Compiler Test 1 Test 2 Test 3 Test 4 Test 5
Metaware 3.187 8.531 2.938 33.406 10.344
VAC++ 2.187 NA 2.282 460.156 NA
Watcom 3.090 18.720 4.910 93.400 20.970
Wat 10.5 2.84 17.63 4.93 95.79 19.34
Borland 3.406 NA 3.032 825.344 NA
Test 1 simply tests the construction and destruction of an object including a
call to it's virtual function. Test 2 is like test 1 except a more complex
object is used. Test 3 is similar to test 1 except that the object is
created/destroyed from within a try/catch block. Test 4 is like test 3 except
that an exception is actually thrown and caught. Test 5 assigns the complex
object to another object. The same complex object that was used in test 2 is
used here.
Test 3 uses 1 less function call than test 1. In theory, it should use up less
time than test 1 unless the amount of time used to setup the try/catch block
exceeds that of a function call. In both the Metaware and Borland test results,
test 3 was faster than test 1.
In the C++ test suit, Watcom 10.5 performed better than version 10a in every
test except those involving C++ exceptions. It seems the new C++ exception
handling code in 10.5 performs slightly worse than the code in version 10a.
The following table shows the compilation time and executable size for the C++
bench mark program. Notice the compile time and executable size decrease
comparing version 10a and 10.5.
Compiler Compile+Link Time (s) EXE size (bytes)
Metaware 59.19 80400
VAC++ 35.35 39936
Watcom 84.63 65898
Wat 10.5 57.22 59269
Borland 14.22 41489
The unzip test compares the compilation time, executable speed, and executable
size for Info unzip version 5.12. The following table shows the results of the
unzip test.
Compiler Compile+Link (s) 'unzip -t unzip512.zip >NUL' (s) EXE size (bytes)
Metaware 629.47 2.37 128579
VAC++ 189.10 2.50 136755
Watcom 232.22 2.07 96027
Wat 10.5 231.91 2.13 96245
Borland 168.53 2.40 140339
Note: although VAC++ compiled unzip faster than Watcom, this is may or may not
be the case. VAC++ takes twice as long to compile the AdeptXBBS source code.
Automatic function inlining had to be turned off in VAC++ because the resulting
EXE falsely reported error in a good zip file. Metaware had inlining turned on.
C++ Compiler Review - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 7.3. Summary ΓòÉΓòÉΓòÉ
Summary
The upgrade to Watcom 10.5 is worthwhile. Compared to version 10a, one gains
remote OS/2 debugging, better performance under warp (although not perfect
yet), and faster C++ compilation times. For those doing tcp/ip programs,
there's finally a alternative to CSet and EMX (a freeware C/C++ compiler). The
cross platform support is great.
Watcom 10.5 works well enough to be the choice for a general purpose OS/2
compiler. It's not a perfect package however, it's extremely versatile and
reasonably priced. Personally, I still prefer using CSet++ 2.1 for debugging
and analyzing code performance. The debugger and profiler in CSet++ 2.1 work
well and do so in a reasonable amount of memory.
C++ Compiler Review - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8. OS/2 Frequently Asked Questions ΓòÉΓòÉΓòÉ
OS/2 Frequently Asked Questions
Written by Dean Roddey
Introduction
As someone who spends a considerable amount of time in the CIS OS/2 developer's
forum and in the OS/2 developer news groups, I've seen that there are a core
set of PM questions that are asked time and time again. The obvious reason for
this pattern is surely the lack of practical documentation on these subjects
I'm sure. Since EDM/2 is geared towards filling this hole in IBM's
documentation, I thought I would add my two cents and answer these questions in
as practical and (hopefully) unconvoluted a manner as possible.
The Subjects of This Article
I will cover a number of topics in this section that rotate around one or other
popular misconception or obscurity related to PM programming. They are not in
any particular ranking or order necessarily. (well ok they are are
alphabetically arranged.) Here is a list of the topics covered:
Changing Window Styles
Dialogs as Main Windows
Dialog User Interaction (and how to do it yourself)
PM Resources and Resource Ids
Presentation Parameters and System Colors
Subclassing/Superclassing
Transparent Windows
Window Extra Data
Window Messages
Window Relationships
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.1. Changing Window Styles ΓòÉΓòÉΓòÉ
Changing Window Styles
A very commonly asked question is "Can I change a window's styles after it's
created?" The answer is maybe, maybe not. It depends upon the particular type
of window. There is, unfortunately, no standard mechanism for doing this kind
of thing. So it becomes just a matter of experience as to what styles you can
manipulate after the fact.
In a Perfect World
The obvious solution to this issue would be a formalized mechanism through
which window styles can be modified, and through which a window could indicate
to a client application what styles it will allow to be changed. For instance
a WinSetWindowStyles() method would take a window handle, a set of new styles,
and a relevant bits mask. It would get the current styles, weave in the new
ones, and then send a message to the window telling it the new styles
(WM_NEWSTYLES perhaps.) The window would look at the current styles and new
styles, update itself with the ones it would accept, and return to PM the
changes it could do. PM would return these to the client code. The update
would be as efficient as possible since the window would know what parts of
itself were affected.
In Reality
However, there is no such thing in PM. To a PM window, its styles are just a
set of bit flags put into a predefined place in the window's extra data words
(see Window Extra Data below.) During window creation, PM will place the
styles (passed to WinCreateWindow) into this area. After that, there is no
formalized usage of the styles flags. Each class of window is free to do one
of 3 things.
Look at the styles on every paint and paint itself accordingly
Look at the styles upon creation and ignore them for evermore
Look at some style bits in manner #1 and some in manner #2
Many simple window classes can work purely on the first 'stateless' principle.
On each paint it just looks at its current styles and paints accordingly. For
these types of windows, the window styles can be easily modified by extracting
the current styles, modifying them as desired, putting them back, and
invalidating the whole window (unless you know for a fact that only a
particular area of the window is affected and can successfully calculate it.)
This is obviously less desirable than the perfect world, since often this
scheme will cause gratuitous repainting which is unsightly and wasteful of CPU
time. But at least it can be done.
Some window classes only look at certain styles once at creation and then
never bother to check them again. The most obvious example is when a
particular window class can optionally create child windows (such as scroll
bars.) Once those scroll bars are created, there is no real reason to look at
those styles again, at least from the window's perspective. One reason for
taking this approach is the very lack of a formalized mechanism for updating
styles. For most controls, the only thing they can really do is look at the
styles during a paint. But, for doing things like creating/destroying/moving
child controls and whatnot, the paint event is not a very good place to do
such things.
Frame Controls
Unlike normal window styles, frames do have a formal mechanism (separate from
the window styles system) for addition and subtraction of standard frame
controls. So, for the most part, you can cause them to come and go as you
please. You just need to destroy unwanted ones or create new desired ones and
then send a WM_UPDATEFRAME message with bits on for the controls you deleted
or want added. Be sure to give them the correct FID_XXX window ids and make
the frame their parent and owner, though some frame controls are not separate
windows and have no id.
Confusingly enough, the frame window class has styles for most of the frame
controls; but, you should only use them from a dialog resource (or so the
documentation states.) When creating a frame via WinCreateStdWindow() or
WinCreateWindow(), you should use the FCF_xxxx values. These are passed in
via a FRAMECDATA structure as the window control data.
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.2. Dialogs as Main Windows ΓòÉΓòÉΓòÉ
Dialogs as Main Windows
Lots of people ask about how to use dialog windows as main windows. The
reasons are obvious, such as being able to draw the windows instead of doing
time consuming positioning calculations and creating them on the fly. Also,
you get the benefit of having the window sized to fit the default system font
on the target hardware. A main window dialog is definitely doable, and it's
pretty easy. But there are a number of different approaches to do it, each of
which has its own pros and cons.
Everyone has used WinDlgBox() to run dialogs but, to understand the best way to
use dialogs as main windows, you need to understand what goes on under the hood
when you call it. Basically two APIs, WinLoadDlg() and WinProcessDlg() make up
the guts of WinDlgBox(), with some extra housekeeping in between. So first a
quick overview of what happens when you create a dialog.
How Dialogs Work
The WinLoadDlg() API uses DosGetResource() to load up the dialog description of
your dialog (see PM Resources and Resource Ids below) from the resources left
in the DLL or EXE by the resource compiler. It uses this description to create
a frame window and all of the individual controls defined by the dialog. The
controls are created in the same order as you put them in the dialog, which
becomes important below. Once everything is created it will subclass the frame
using your dialog procedure (see Subclassing and Superclassing below) and send
you a WM_INITDLG message.
Once done with all of that, WinLoadDlg() destroys the dialog definition buffer
and returns. Note that it only creates the windows and gets everything set up
but nothing else. The frame was left invisible so you don't see it yet (unless
you showed it during WM_INITDLG processing.) At this point, the frame window
is no different than if you had manually created it, and its controls,
yourself. So, as far as windows go, a dialog is very literally a frame window.
It is only special in the fact that it is subclassed by a cooperative party
(you) and that it is processed differently. You are the cooperative party in
that you voluntarily pass any unhandled messages to WinDefDlgProc(). Much of
the magic of dialogs is really in WinDefDlgProc(). It provides the standard
dialog style responses to incoming user and system input. If you did not pass
messages to WinDefDlgProc() then you would not get any of the standard dialog
reactions.
Modal Message Loops
When a dialog is being processed, you've probably noticed that it will not let
any input go to the other windows of the program. It is in a 'modal message
loop'. When you run a dialog, your message loop is no longer being used.
Instead, a message loop inside PM is getting input. This gives it control over
where user input messages go to or if they are allowed to go anywhere at all,
since input messages are always posted and therefore come in via a message
loop) .
The WinProcessDlg() call is what provides this modal loop. It does the usual
WinGetMsg() and WinDispatchMsg() calls, but also watches for dialog specific
circumstances such as the dismissal of the dialog. WinDismissDlg() does two
things, it stores the caller's return code parameter in the frame's extra
window word (at QWS_RESULT) and sets the FF_DLGDISMISSED flag in the frame's
QWS_FLAGS window words. WinProcessDlg() will check the dismiss flag and see
that its time to return. So it will pull the result code from the window's
extra data and return it to the caller as the result code of the dialog.
Theoretically, you could clear the dismissed flag and call WinProcessDlg()
again to start up the dialog again. But it would look ugly because the dismiss
would hide the dialog and then it would reappear again. I have not tried it
myself, but you can give it a try if you think it would be useful.
Also, you could theoretically create a frame, and any desired control windows
within it, subclass it to a dialog procedure and then call WinProcessDlg() to
process it modally as a dialog. WinProcessDlg() probably wouldn't know or care
that the windows were created manually instead of as a dialog resource. Just
be sure that you subclass it to a window procedure that is written like a
dialog procedure, i.e. it uses WinDismissDlg() and passes unhandled messages
to WinDefDlgProc().
WinProcessDlg() does not destroy the window when it returns, but it does make
it invisible. If you use the separate load and process steps yourself, then
you must destroy the dialog frame. If you called WinDlgBox() it will destroy
the frame before it returns, and it will pass on back to you the return that
came back from WinProcessDlg().
The Easy Way Out
The easiest way to have a dialog as a main window is to just do the usual
WinInitialize() and WinCreateMsgQueue(), then use WinDlgBox() to run a dialog.
When it returns, terminate and exit. Having the dialog do all the work is
nice, but it is also the reason why this is sometimes not the best way to do a
main window as a dialog. For starters you don't have a lot of control and some
of the standard dialog processing is not really appropriate for main windows.
For instance:
1. Definitely don't just destroy the frame window when you use this scheme.
That will not cause the modal message loop to exit, but it will destroy
your ability to interact with your program. So basically the program
will just be hung.
2. There are certain dialog'isms like the fact that pressing escape will, if
the WM_CHAR message gets to WinDefDlgProc(), cause a dismissal of the
dialog, thus exiting your program. This is not always desired behavior
for a main window.
3. You cannot do the usual step of allowing the user to back out of an exit
because you don't have control over the message loop.
The Next Step
The next step up the ladder of complexity vs flexibility is to use the
WinLoadDlg() API to load up the dialog and then enter your own message loop,
so that you are not processing it modally. As discussed above there is
nothing magic about a dialog window itself, i.e. using WinLoadDlg() is not
much different from you creating the frame and controls yourself, or at least
the results are not. But once you move to this non- modal dialog style, you
are not really a dialog any more, so you don't want to keep calling
WinDefDlgProc() or otherwise acting like you are still a dialog when you are
not. You can still pretty much get away with such things but you might run
into some interesting problems. For instance, if you just dismiss the dialog
on a WM_COMMAND (as a normal dialog would), you will end up with a hung
program (from the user's perspective.) The dialog will be hidden but the
window will not be destroyed and no WM_QUIT will be issued to the message
queue to cause the program to exit. There are some other small problems of
that sort, that are liveable but can bite you or confuse your users.
What I suggest is this. Use WinQueryClassInfo() to query the class info for
the WC_FRAME class. Remember that the class name for a standard PM controls
is not a real text string but a magic pointer, so the name you pass to
WinQueryClassInfo() is in the form "#0000x", where x is the number from the
defined WC_FRAME value (look in PMWin.h). This information structure has the
address of the original frame class' window procedure. If you now pass
unhandled messages to that procedure instead of WinDefDlgProc(), you will
effectively bypass the dialog specific processing and turn your dialog into a
regular subclassed frame window. Keep in mind that you should still handle
WM_INITDLG to do any setup if you want to, but you will not see WM_CREATE
because the window is already created before it is subclassed to your dialog
procedure. If you now just get rid of WinDismissDlg() and you have a pretty
normal frame window. If you don't need the subclass anymore, for instance
because your dialog has a client window, you can call WinSubclassWindow() with
the original frame window class. This will get rid of your subclass and save
processing effort in the process, since every frame message does not have to
go through two layers before it gets handled. I haven't tried it but you
could possibly pass the original frame procedure as the dialog procedure and
not have to have a dialog proc at all? You try it though and let me know, and
I will use it if it doesn't waste your partition table or anything. (I'm so
brave. [grin])
As an aside, WinDefDlgProc() is really doing the same thing itself internally,
handling some messages and passing others on to the original frame procedure.
You are just skipping the middle man by doing this yourself.
Though this is the most technically correct approach, it does have one down
side. You loose the automatic tabbing support that WinDefDlgProc() provides.
This though is very easily dealt with. See Dialog User Interaction below for
a discussion of this issue.
The Ultimate Control
The ultimate control of dialogs is accomplished by manually parsing the dialog
resource and creating the controls yourself. That is a pretty large subject
so I will not cover it here. However you might want to read my article in the
July/Aug 1994 issue of 'OS/2 Developer', which covers this subject pretty
well. Given the information in this article and that one, you should be able
to handle it with a little experimentation. This knowledge is also useful for
creating your own dialog editor if you care to do such things.
I use this method in my CIDLib class libraries, which allows the TDialogWnd
class to be very expandable. Its constructor provides a callout (which is
called for each new control parsed from the resource) so that the calling code
can optionally override the type or attributes of each control. It's a pretty
powerful and flexible system, but without all the work of providing your own
screen builder (though I will probably do that eventually.) Dialog User
Interaction
For various reasons, people often want to understand how tabbing in dialogs
works. Sometimes, as in the previous section, they've loaded a complex dialog
as a main window and want to retain the tabbing capability. Other times, they
have a similar complex set of controls that they have created manually and
want to provide tabbing for them. This section provides some background on
how tabbing works and tells you how to easily provide it for yourself.
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.3. Window Enumeration ΓòÉΓòÉΓòÉ
Window Enumeration
The basis of tabbing is the ability to enumerate all of the children of a
particular window. The WinBeginEnumWindows() API will begin an enumeration.
You provide it with the window whose children it is to enumerate. It will
return you a handle, which it uses to maintain an internal state table for the
enumeration session. Once you have an enumeration handle you can use
WinGetNextWindow() to get each successive child window handle. When done, you
use WinEndEnumWindows() to close the enumeration handle. WinGetNextWindow()
will return a nul handle when it hits the end of the list.
The Z-order of the child windows drives the iteration process. In other words,
the windows are enumerated in their defined Z- order. This is why the order of
creation of controls in the dialogs is important for the desired tabbing order,
as you will see in the next section.
Window enumeration is a fundamental type of magic that is behind many cool
utilities that show you the hierarchical arrangements of any process' windows.
You can use it to good effect sometimes, so check it out.
Tabbing Enumeration
Tabbing is accomplished via the WinEnumDlgItem() API. This API is not magical
in any way, and just builds upon the basic window enumeration system discussed
above. It effectively just enumerates the child controls of a particular
window, queries their styles, and looks for WS_TABSTOP and WS_GROUP style bits
to decide what to do. It can answer questions like, "From the current focus
window, what is the first/last control in the next/previous group" or "From
this particular window, what is the next window that has the tabstop style" or
"What is the next/previous window in the same group". The tabstop and group
styles really have no other use, so they are often not used when you create
controls manually. But, if you want to provide tabbing for manually created
controls, you must apply them.
As is often times the case in PM, the Dlg part of the name in WinEnumDlgItem()
is a misnomer. It is called that because that's all OS/2 itself uses it for.
However, you can use it on your own frame windows, non-modal dialogs, or on the
children of your client window, to easily provide tabbing without having to use
dialog processing. You always call it with a parent window whose children it
is to enumerate, so there is no ambiguity about what window it is operating on.
When a dialog is loaded, the loading code will create the controls in the order
they are found in the dialog definition, giving each one HWND_BOTTOM as the
z-order. This effectively stacks the controls up in the same order as they
were drawn by the dialog editor (or manually written by you into a dialog
definition.) When you want to provide tabbing for your own manually created
controls, you just need to make sure to create them in the correct order and
give them the desired tab stop and group styles, just as though you would have
done them in a dialog editor.
Doing It Yourself
If you want to provide your own tabbing, I would suggest that you write a
single function, say bDoTab() or something similar, that is just a wrapper
around WinEnumDlgItem(). That way, in every application, you can just put a
call to it in your client window's WM_CHAR message handling. It will look at
the character and see if it is a tab or arrow key or Alt-mnemonic character. If
so, it will do the enumeration and move the focus to the new focus window,
returning TRUE to say it handled the message. The WM_CHAR code should then
just return TRUE to say it was handled. Otherwise, it returns FALSE and the
WM_CHAR code should pass it on to the default handler or eat it or process it
as needed. The type of character (tab, back tab, up, down, left, right)
controls the third parameter to WinEnumDlgItem(). This parameter is one of the
EDI_xxxxx values, which tell WinEnumDlgItem() what kind of enumeration to do.
To really work like dialogs do, you also need to check for mnemonics. So, if
the Alt key is pressed and the WM_CHAR message is a character message, you
should enumerate the child windows and send each one a WM_MATCHMNEMONIC
message. If a control responds back saying that it matches the mnemonic
character, put the focus on that control.
If the character is an Enter key, then enumerate the children and send each one
the WM_QUERYDLGCODE message. This will cause the child window to return a set
of DLGC_xxxx bit values. You just need to look for one that has the
DLGC_DEFAULT bit on and send it a BM_CLICK message. This will cause that
default button to send a WM_COMMAND message as though the user clicked on it.
There are some more obscure features you might have to deal with to get exactly
the same results as a dialog but those are the most common ones and should
serve most apps. And some of the dialog processing, as mentioned above, is not
desirable for a normal window anyway. Of course, if you are doing a class
library, then the tabbing support should probably be implemented in the basic
window class so that all windows can optionally provide tabbing for their
children. In my class library, the TWindow class has an 'autotab' attribute.
If set, it calls its internal tabbing support wrapper function. This makes it
trivial to provide tabbing any time its desired. If the character input causes
a tab operation, then the window is not even bothered by telling any input
occurred so the support is transparent and automatic
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.4. Font Ids ΓòÉΓòÉΓòÉ
Font Ids
Font ids can cause no end of problems if they are not managed correctly.
Unfortunately here as well there is just not sufficient documentation of the
big picture. Each process can have up to 255 logical font ids in existence at
once. Since font ids are associated with a presentation space, and most
presentation spaces are cached and therefore have short lifetimes (usually just
for a WM_PAINT), the maximum number of font ids is usually not an issue. Other
applications, such as those which create persistent presentation spaces or more
complex ones that have separately developed black box subsystems or that have
multiple drawing threads, correct management of font ids is important.
The simplest application is one that never uses any other font than the default
system proportional font. Such programs have no font id management issues
because the 0th font id always magically exists. For more complex software the
two biggest problems with fonts are that multiple, separately developed,
subsystems fight over the same ids and/or the leakage of font ids. The first
will create weird problems because creation of logical fonts will fail (due to
the id being in use by someone else) or logical fonts will be destroyed behind
the back of someone who is using it. The second will eventually bring the
application to an eventual, often non-obvious demise.
Font Id Management
The first step in font management beyond just using the system proportional
font is to define a set of global defines for the fonts to be used by the
program. If only one thread does all painting via cached presentation spaces,
using font ids set up and then torn down all within the WM_PAINT code, then
this scheme will work fine and all windows can share the same logical font ids
without any conflict. It's simple and easy to understand, as long as the
program is simple.
Once a program starts creating persistent presentation spaces, which can cause
font ids to be in use outside of WM_PAINT code, or using multiple GUI threads,
which can possibly have font ids in use simultaneously, the issue of font id
management needs to be more formalized. Though a program can certainly provide
its own font id management system, there is one built into PM that works well
enough. You could though improve upon it if you felt it worth doing.
The GpiQueryNumberSetIds() API will return the current number of font ids in
use by the process (which are also used for custom patterns by the way, so this
number may not just reflect fonts). The GpiQuerySetIds() API will return
information into 3 separate arrays (confusingly allocated as a single block of
memory though) that tell you about the font ids in use by the process. Using
these two APIs, you can determine what ids are currently in use and, by
extension, figure out one that is safe to use.
ulGetNextId()
The easiest way to use the PM font id management APIs is to write a
function/method named, for instance, ulGetNextId(). It will find and return
the next available id using the APIs mentioned above. The only catch here is
that, if you have multiple GUI threads or are writing general purpose code that
might have to handle that situation, you must make the finding of a new id, and
its being put into use, an atomic operation that is protected by a semaphore.
The reason for this precaution is that GpiQuerySetIds() API doesn't care
whether you've checked and found an id you liked. It only knows which ones are
in use. If you use it to find an unused id, then another thread gets scheduled
before you get the id into use and calls ulGetNextId(), it would get the same
id. One of them would later lose when trying to create a logical font with
that id, causing errors from weird displays to outright crashes.
So you really need another layer of code above the ulGetNextId() call. You
need to provide APIs that lock a common semaphore, get an id, create logical
fonts or custom patterns, then release the semaphore. This synchronization
will insure that your management of font ids are thread safe. In most
programs, just the natural synchronization of PM's message passing architecture
will insure that the semaphore is not actually ever needed. But even in single
threaded programs its just safer to do that small amount of work and never
worry about it again.
Of course, none of this helps if you must link to 3rd party code which chooses
not to play with you. It cannot know ahead of time what your locking scheme
will be so you should assume (unless told otherwise) that it will probably use
font ids (if at all) in the most optimistic manner, as discussed above. If you
are working from some common base library code it should definitely provide
such an API for all to use.
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.5. PM Resources and Resource Ids ΓòÉΓòÉΓòÉ
PM Resources and Resource Ids
Some of the most obvious missing pieces of information in the OS/2
documentation is related to the use of resources and resource ids, and the
possible schemes for managing them. Each OS/2 resource has a type (defined by
the RT_xxxx values in BSEDOS.H) and an id. When you watch the resource
compiler putting out numbers like 3:100, that means a menu (RT_MENU is 3) with
the id 100.
The type and id values are used to extract the resource from a particular DLL
or EXE module, using the DosGetResource() API. You might never use
DosGetResource() yourself, but that is the underlying API that extracts a
resource into a system allocated memory buffer. A program does not have to be
a WINDOWAPI program to access resources in this way because the actual resource
is not created, just the description of it is loaded.
The Resource Id 'Name Space'
Since you must access a resource by providing the module handle of the DLL or
EXE module that it is attached to, there is effectively a 'resource name space'
with three levels. So a particular resource has a 'path' like this:
\HModule\RT_xxxx\Id
This means, though it never seems to be pointed out, that the type:id pairs are
automatically unique within each DLL or EXE module. So, for instance, you can
have a bitmap with an id of 1 in every single Dll in a program and there will
be no problem with id conflict. There can also be a bitmap and a string and a
dialog with the id of 1 within a particular DLL or EXE. This is particularly
convenient ("Nay, absolutely required," he said in a regal manner), when
building black box DLLs for distribution or doing large, multiple group
development. You just don't have to worry about resource id distribution
except within a particular DLL or EXE module.
Resource Access APIs
You will generally access resources via a set of higher level (read PM
oriented) APIs which themselves use DosGetResource() to load up the raw
resource description. These APIs then use that description to build the actual
PM resource, after which they can discard the raw buffer. WinLoadString(),
WinLoadDlg(), WinLoadPointer(), etc. are examples of these convenience
resource APIs. You could easily (relatively speaking of course) replace these
APIs with your own and enhance or expand on them, because they are not magical
in any way and have no privileged knowledge or system access. The format of the
raw buffer is, as far as I know, the exact format from the .RES file that was
attached to the DLL or EXE. Finding the details of that format for some of the
resource types is though sometimes like drawing blood from a stone.
For instance, in my class libraries, I wanted to have a strict separation
between GUI and non-GUI code but wanted to have string resources accessible in
the lowest level (kernel encapsulation) DLL. So I provided my own methods to
extract string resources. Tehnically I could probably call WinLoadString()
with a 0 HAB, but I did not want to cheat. Its quite simple and you can do
things like cache the most recently accessed strings for fast access (if that
makes sense for your access patterns.) String resources are actually grouped
in sets of 16, called string tables, so you extract them in these tables and
pull out the particular one of interest. So caching this table is the most
convenient way to keep them in memory. This also makes it most efficient to
group your strings (if they are not all just consecutively numbered) so that
they start on ids which are multiples of 16.
While I'm spending your development dollars here, another good use of this
technique is in a scalable interface. Lets say you wanted to provide a 4 level
interface (from expert down to severely challenged, for me), you could arrange
your string ids such that each 'message' started on a multiple of 16. But a
'mes sage' would actually be 4 strings at successive ids starting from the
first one. The program itself would just ask to load the 'message id' which
would be the id of the first string in each group. The loading function would
pull in the string table for that 'message' and then use the program's current
interface level to return the actual string for that level. Having the base id
for each message an even multiple of 16 insures that all of its related
messages are in the same string table and loaded together.
I also use DosGetResource() to load up dialog definition resource buffers and
use that template to create my own dialog windows. This gives me more control.
See Dialogs As Main Windows above.
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.6. PresParams and System Colors ΓòÉΓòÉΓòÉ
PresParams and System Colors
Though they are relatively well covered in the documentation, presentation
parameters and system colors (or at least their proper usage) are not well
known. Part of the problem is that their relationship to the standard
controls, their relationship to each other, and how custom controls should use
them in order to be good citizens is definitely not explained clearly enough.
The Standard Controls
The best way to see the intended use of presentation parameters (or presparams
as they are called) and system colors is to look at how the standard PM
controls use them. A basic requirement of the standard controls (because of
how widely they are used) is that they be configurable to the greatest degree
practical. An obviously important area of configurability for a control is
that of the colors and fonts used in drawing itself. So they all have a logic
kind of like this:
For drawing my foobar, I will use presentation color X
If presentation color X is not present I will use system color Y
So, when you use the system color palette to set a system wide color (by
holding down Alt when you drag and drop a palette color), you are setting a
particular system color. You can also do this via your own programs, so you
can create your own system palette manager if you desire. There is nothing
magical about the system palette widget. So every window which has not had
presentation color X explicitly set on it will use the new system color Y. In
order to make everyone update immediately, every window is sent a
WM_SYSCOLORCHANGE message and the screen is redrawn by invalidating all
windows.
In order to allow particular windows to buck the trend and have their own
color/font scheme (while still remaining user configurable), PM supports
presentation parameters. PM supports a predefined set of presentation
parameters which are used by the standard controls (and user programs if they
care about presentation parameters at all.) Dropping a color on a window
(without holding Alt) will cause the new presparam to be stored on the window
and a WM_PRESPARAMCHANGED message to be sent to it. Its reaction will be
similar to the WM_SYSCOLORCHANGE discussed above. Presentation colors/fonts
are set via the WinSetPresParam() API and queried via WinQueryPresParam().
They can be removed via WinRemovePresParam(). The WinQueryPresParam() API
will automatically search up the ownership chain of the target window, if you
ask it to, searching for some ancestor window with that particular
presentation parameter. I assume that this is intended to allow a single
owner window to control the appearance of its owned windows. When a color or
font is dropped on a window, PM just calls WinSetPresParam() on that window.
The important things to remember here are that system colors only have to be
stored once for the whole system and that all windows call APIs,
WinQuerySysColor() in this case, to get their values. Presentation parameters
are stored separately for each window on which they are set. PM maintains
this storage for you and keeps each window's presparams associated with the
correct window handle.
Don't try to read any rhyme or reason into the names of the
system/presentation colors used by a window for a particular attribute of its
appearance. There are a set of predefined, and pretty generically named,
colors. In order to avoid massive proliferation of them, the standard
controls will just pick from that list ones with names that are hopefully
somewhat related to the purpose for which they are used (but sometimes
seemingly unrelated at all.) The documentation on what standard controls use
what colors, is extremely pathetic. So its only through the patient
experimentation of you and/or others that most of them get figured out. If
you have IBM on-line documentation, open the PM Reference and search for
"Default Colors" to get about as much as you are likely to find. And even
this documentation only says what they system/pres colors are, not what visual
aspect of the control they are used for.
Blending Into the Crowd
So, if you want to write a control window that acts like a standard control in
its use of colors and fonts, you must take a couple of steps. The most
obvious is to write a wrapper function that takes a system color and a
presentation color. It will first look for the presentation parameter and
return it if found, else it will query the system color and return that. This
function then provides the basis for the paint logic's use of colors, while
moving lots of possibly replicated grunt code to one place.
You can take two approaches to the presentation colors and system colors your
window uses. You can either just be very stateless and query them on every
paint, or you can cache them. In the later scheme, you set them initially via
a manual query and thereafter update them on any WM_SYSCOLORCHANGE or
WM_PRESPARAMCHANGED message. Your window class would just call, for instance,
a SaveColors() function initially upon creation and then upon receipt of
either message thereafter. This would keep all of the code in the same place.
Custom Presentation Parameters
You can create your own presentation parameters by using values greater than
PP_USER. The system will not send them to you of course since it doesn't know
them from Adam, but you can send them to your own windows. If you set them on
'foreign' windows they will just be ignored (though PM will store them on the
window anyway) because those windows will not understand them. Worse, they
might have defined their own custom params with the same id (and different
data layout) and freak out.
Saving/Reload Presentation Parameters
The WinStoreWindowPos() and WindowRestoreWindowPos() APIs will save and
restore the size, position, and presentation parameters of a window. The
information is stored in the system INI file, so you have to provide the
application and key names to use. These may or may not be very useful to you,
and the same functionality is pretty easy replicated on your own if these do
not do exactly what you want.
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.7. Subclassing and Superclassing ΓòÉΓòÉΓòÉ
Subclassing and Superclassing
PM provides two simple (though loose and not very formalized) mechanisms for
inheritance with window classes, called subclassing and superclassing. If I
want to have a button that acts just slightly different than the standard push
button, it makes more sense for me to try to just affect the behavior that I
want to change and let the other functionality be handled as it was before.
Actually, in this case, I could possibly make it a user-drawn button but that
is a special case as it only affects visual behavior, and muddies the waters of
this discussion for the moment so pretend it does not exist. Let's say that I
need a way to affect just the click of button 2 so that it pops up a help
screen for that button, so really all I want to do is change what a button2
click does.
Subclassing
Since almost all stimuli that affect a window come in the form of messages, if
you can get the messages to come to you first, you can handle the ones you want
and pass the others on to the original recipient, letting him/her handle them
as before. The simplest mechanism for doing this is to subclass the window,
via the WinSubclassWindow() API. You pass the window handle of the window you
want to subclass, and a new window procedure. PM makes your new window
procedure the new recipient of all messages coming to that window. It also
returns to you the address of the previous window procedure, so you can pass
any unneeded messages on to the original procedure. Actually you have a number
of options:
Handle the message and return without letting the original see it
Provide some preprocessing, then pass it onto the original
Let the original handle it first, then provide some post processing
Let it go straight to the original window procedure.
As far as I know, the window procedure to which a window's messages go is
always stored in the QWL_PFNWP window words, so most likely all
WinSubclassWindow() does is get the current value out, put the new one in, and
return the old one. So you could easily do this operation yourself if you
chose to do so. When a window is first created, this value is set by looking
up the window class passed to WinCreateWindow() and getting out the window
procedure given when the window class was registered via WinRegisterClass().
Now we can provide the special processing for the button by trapping
WM_BUTTON2DOWN and WM_BUTTON2UP and doing our special processing on the up
event. In this case we would not pass them on to the original since we don't
want it to take its default action of posting a WM_COMMAND to its owner.
Dialog windows are subclassed frames. When you call WinLoadDlg() or
WinDlgBox(), you provide your dialog procedure address. After WinLoadDlg()
(which is in turn called by WinDlgBox() if you call that) creates the frame
and the controls, it then calls WinSubclassWindow() on the frame using your
window procedure and saves the original frame procedure. So messages first
come to your window procedure letting you deal with it. If you pass it to
WinDefDlgProc() it will possibly handle it, in order to provide standard
dialog functionality such as tabbing, or pass it on to the original WC_FRAME
window procedure. So the effect is of a layered set of 'virtual message
handlers' that cooperate in providing an extensible feature set, with each
layer taking one of the above 4 approaches to each message received.
Superclassing
Superclassing is less often done than subclassing because its advantages,
though sometimes significant, are often not needed enough to justify it. The
best way to understand the differences between subclassing and superclassing
is to realize that subclassing is for applying per-window overriding of
messages. In order words, subclassing is done on a per-window basis, after a
window has already been created. The creator of the window usually decides
whether he/she wants to apply the subclass, not the window itself. Another
disadvantage of subclassing is that, since the window must already exist in
order to subclass it, the WM_CREATE processing happens before the subclass can
be applied.
It would be nice to be able to extend, limit, or otherwise modify the
functionality of an existing window class such that it applied to all
instances of that window (without explicit action having to be taken by the
client code.) Superclassing provides these benefits. To superclass a window
you must follow these steps.
Query the class information of the class to super class
Store away the count of extra data words it has and the window procedure
of the class
Register a new window class, providing your own window procedure when you
register the class.
If your window class needs any extra window data beyond that of the
original class, add your needs to the original class' when you register
your new class. One reason you might want to create extra window words
is to have a place to store per-window information without using the
QWL_USER area that the users of the new window class might need.
The important things to note here is that you have created a new window class.
So, when client code creates the window, it will provide your window class to
WinCreateWindow(). This has important ramifications to your control of the
situation. They are:
Since the client is creating your window class, you will get the
WM_CREATE message. Make sure that you pass it on to the underlying
window class first, to let it handle its initialization. Then take care
of your own initialization needs.
You are in control of the situation. You don't need to count on client
code to create a window of one class and then apply some subclass you
provide to it. This means that the superclass will naturally apply to
all instances of the window, not just to selected instances of it.
You get to add more per-window instance data words, which is often
necessary. You cannot use any existing window words because they could
all be used by the window class you superclassed (or by per-instance
subclasses applied by client code.) By adding your storage needs to the
underlying class' your data is at indexes beyond those accessed by other
users of the window (because they don't know they even exist probably.)
You can tell at runtime whether a window is of your particular class
because you can query its class name or class info. There is not an easy
way to tell if a subclassed window has had a particular subclass applied
to it. You cannot just compare its stored window procedure address with
your class' window procedure because it could have been subclassed as
well by client code.
Owner Draw
Some standard controls support an 'owner mode'. This is not a subclass or
superclass because, in this case, the control is just letting its owner window
handle a particular aspect of its visual appearance. Subclassing and
superclassing are applied to the control window itself and prevent the
parent/owner windows from having to be particularly aware of them once they
are set up.
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.8. Transparent Windows ΓòÉΓòÉΓòÉ
Transparent Windows
Lots of people ask how a window like a combo box can cover a large part of the
screen but only make use of the bottom part when it drops down the window. It
does not affect the underlying windows any other time, letting you get straight
to the windows underneath via mouse clicks. And you can write a small program
to check that the combo box is not changing its size when the drop down list is
lowered. It is that size all of the time, also obvious when you use the dialog
editor to draw them.
Effectively what is happening is that the combo box is selectively making parts
of itself transparent visuall and to input. Now everyone probably knows that
its easy to make a window visual transparent by just not drawing anything
during its painting events. Usually they first find this out by accident and
wonder why their window seems to be dragging around a bit of the desktop
background. But how do you make the window selectively transparent to mouse
clicks?
Hit Testing
When it is time to dispatch a mouse event to a window, PM will send it a
WM_HITTEST message. The window can respond it one of four ways by returning
one of the HT_xxxx values.
"Yes I'll take that mouse event", HT_NORMAL
"I'm transparent at that point so let it pass on to lower z- order
windows', HT_TRANSPARENT
"I can't take it but I'm not transparent either so don't pass it on",
HT_DISCARD
"Its an error for me to get a mouse event now", HT_ERROR
In the first instance, the event is passed on to the window. In the second
case, WM_HITTEST is passed to the next control in the z-order chain that
contains the coordinate of the mouse event. In the third case, the event is
just eaten. In the last case, the window is brought to the foreground and PM
beeps at you, but the mouse event is otherwise eaten with no effect. This is
how disabled windows can easily ignore mouse events but still get the required
button down effect of coming to the foreground.
From that explanation, it's probably pretty obvious now how a combo box does
its thing. When it gets a WM_HITTEST, it checks whether the event is over a
part of itself that is not transparent. If the list is dropped down, then
either the list box or entry field will get the message and just return
HT_NORMAL. If the button hits the backing window, because the list box is not
covering it, it just returns HT_TRANSPARENT and the button goes on to the
window that is visible 'through' the combo box.
Handling Your Own Hit Testing
In your own window classes you likely never need to handle WM_HITTEST. You
can just let it pass on to WinDefWindowProc(), which just returns HT_NORMAL to
let the mouse event come to the window or HT_ERROR if the window is disabled.
This is the correct behavior 99.99% of the time. If you do need to handle it,
just use the passed mouse position to determine if your window is transparent
to mouse input there and return the appropriate hit test result. This result
will be passed to the actual mouse event later, as one of the message
parameters (which is probably pretty universally ignored but its there.)
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.9. Window Extra Data ΓòÉΓòÉΓòÉ
Window Extra Data
Under PM, since every window of a given window class shares the same window
procedure, there must be a mechanism for each instance of a given window class
be distinguishable. This is accomplished by every window having a window
handle which is passed to the window's procedure for each message received.
Associated with each window handle is a small amount of extra data storage that
is recreated for each instance of a window class. Since this window data is
associated with the window handle, the window procedure can be totally
independent of which window is calling it. The window procedure becomes a
state machine and the window's extra is the state storage area, in which the
window remembers its current state until the next message is received.
Of course this whole argument applies to the less common use of window classes,
which is to create a standard window type that can be used by many different
subsystems or processes simultaneously. Some PM programmers have only had need
to create a window class for their own client windows or dialogs. Since there
is usually only one instance of these windows ever in existence, global
variables might be used to track state information. That is a valid approach
in these cases, but PM makes it trivial to make even these windows inherently
reentrant so that they can easily be instantiated multiple times in the future
if needed.
Just FYI, you can also use the same window procedure for multiple classes of
window. Often times, if I have multiple small dialogs in a single module, I
will make one dialog procedure and use it for all of the dialogs. The id of
the dialog can be used, within each case of the switch statement used to
process the individual messages, to determine the correct action to take. So
the dialog procedure is really a nested set of switch statements. The outer
one gets you to the correct message handling code. Within the case for each
handled message is a switch on the id of the dialog, which will usually call
out to a function appropriate for each dialog. Sometimes, if the code is
trivial, it can just be done right there in the second switch. This scheme can
cut down on redundant code and keeping track with what dialogs use what dialog
procedures, but it has its own set of possible gotchas.
The extra window data of a window is accessed via a set of APIs named
WinXXXWindowULong(), WinXXXWindowUShort(), and WinXXXWindowPtr(), where XXX is
either Query or Set. There is an extra WinSetWindowFlags() that sets bits in a
32 bit field of extra data. There is not a WinQueryFlags() because
WindowQueryULong() is fine for reading them. There is a separate flag setting
API because it provides a 'relevant bits' mask parameter which lets you
indicate which actual bits you want to affect. Otherwise, you would have to
query the existing flag field, weave your changes in, then write them back.
Instead you can do all that in one operation.
When you call these APIs, you tell it the index of the memory field you want to
access or set. These indexes come in two forms, as is discussed next. But the
bottom line is that the data is not just a flat memory buffer for you to access
at will but a special area that must be accessed via an API.
The Blessed Data, The Common Data
There are two 'classes' of window data. One set is defined by PM and its
somewhat magical and the other is window data created by the outside world. In
this case the outside world is any window class, including the built in window
classes. These magic window data fields are created automatically for every
window so they are always available. The data created by each window class for
its windows can vary from window class to window class. The amount of memory
that a window class needs is indicated when the class is registered by
WinRegisterClass().
The indexes for the magic window words are easily recognized in PMWin.H. They
are the QWL_xxxx and QWS_xxxx values that have negative numbers. All
non-blessed window words have indexes of 0 or greater. There are other window
word indexes defined in PMWIN.H, for the frame window class for instance, but
they are for window class data and have positive indexes.
If you look at the indexes for the magic words and the ones for the frame
window class, you will notice something interesting. The window class specific
data seems to be laid out as a single buffer, though I said it was not above.
For instance, the QWL_xxx values each start at an index 4 bytes beyond the last
one. The fact is that the class specific data probably is a contiguous buffer,
but you are not supposed to assume that because it might change. The indexes
of the magic words obviously have no relationship to the size of the values
they point to. They are just sequentially numbered negative numbers. This
probably implies that these values are just stored in various internal
structures and the special indexes trigger the access APIs to go get them.
Since the class specific data really is like a contiguous range of bytes that
can be referenced at any offset, you can use WinQueryUShort() to query the low
or high word of a field that is actually 32 bits just by adjusting the offset.
This line would query the top two words of the QWL_USER field. This would not
work with the system defined values because they are not indexes in the same
sense.
USHORT usVal = WinQueryWindowUShort(hwndMine, QWL_USER+2);
Ad Hoc Window Data
It is important to note that most window data is 'class wide' meaning that is
used in the same way by the window procedure for all instances of that window
class. But, for very general purpose windows such as the standard PM controls,
there is very often a need for some storage that can be used in an ad hoc way
by each individual instance of the window. So, all of the standard controls
provides a user definable area, QWL_USER, that can be used differently by each
instance of the window, because it accessed by client code not by the window
procedure. If you write very general purpose window widgets, this is a good
practice. QWL_USER is defined as 0, so it is the first index in the class
specific window words. But you should probably not assume it will remain so
defined. If you create symbolic names for the indexes of your window words,
you should technically do them as offsets from QWL_USER, such as QWL_USER+4.
This way they will adjust automatically.
The section on Subclassing and Superclassing above covered one way to extend
the window storage of a predefined window class. This is sometimes needed to
allow extension of the class wide storage while still leaving the user
definable storage area alone.
Frame Window Words
The frame window class has the most class defined storage words of any of the
predefined controls, about 0x54 bytes or so it seems from perusing the headers.
Partly this is because some of them are used when a frame is in 'dialog drag',
and partly because the frame control has the most need to play magic tricks in
the process of providing standard system functionality. For instance, when a
frame is activated, it will put the focus on the last of its descendant windows
that had the focus. This is accomplished by its storing the current focus
window into QWL_HWNDFOCUSSAVE, when it gets a WM_ACTIVATE message indicating
that it is being deactivated. When the frame is minimized or maximize then
restored, it goes back to its previous position. It does this by saving away
the current size and position in QWS_XRESTORE, QWS_YRESTORE, QWS_CXRESTORE, and
QWS_CYRESTORE, when it receives a WM_ADJUSTWINDOWPOS message indicating that it
is being minimized or maximized. QWL_FLAGS holds a set of bit flags that give
lots of information about the current state of a frame window.
Stupid Window Data Tricks
You can often play nice tricks by knowing the content of the system defined or
class defined window words and adjusting them as desired. As discussed above
in Changing Window Styles, you can sometimes extract the QWL_STYLES words,
modify them, and put them back to change the styles of a window on the fly. As
far as I know, you can write a new value to QWS_ID to change the id a window
(including to accidently setting it to the same id as another child, which can
cause weirdness later.) If you want to control the position to which a frame
window will restore, then adjust the restore window words discussed in the
previous section. On restoration, the frame window will pull these values out
and uses them to restore itself. For a dialog, you can, as far as I know,
reenter the dialog after WinDismissDlg() is issued (assuming you used
WinLoadDlg()/WinProcessDlg() instead of WinDlgBox()) by clearing the
FF_DLGDISMISSED flag and calling WinProcessDlg() again. If you leave
FF_DLGDISMISSED set and call it, it will probably just hide itself immediately
because it will think it is already dismissed. You can change the window to
which focus will be put when the frame is activated by changing
QWL_HWNDFOCUSSAVE. Though I have not done it myself, I think you can adjust
where the frame will minimize to the next time by adjusting the QWS_MINIMIZE
and QWS_MAXIMIZE words. I assume that, when the minimized frame is moved it
updates these with the last place it was dropped (or maybe it just waits until
its restored and does it then.)
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.10. Window Messages ΓòÉΓòÉΓòÉ
Window Messages
Window messages are pretty well explained in the documentation, however there
are a few less understood issues surrounding them that I wanted to cover. Of
course the reason PM uses messages is that the system must dynamically link to
code in the client's program, because it does not know ahead of time what
windows the client code will use, how many of them, where their window
procedures are, who will subclass them, etc. So, instead of having a window
provide virtual functions to call (like an object oriented system would), it
allows each window class to provide one function pointer which it will call
back when events occur. Since it only allows one function, the message id is
passed in order to allow multiple actions to be overloaded on this single
function. It's definitely not very type safe but allows a kind of flexibility
that would otherwise not be very feasible for a procedural system.
System Defined vs User Messages
The system defines a number of messages, by defining a set of ids in the
toolkit headers. There is nothing to keep you from using these message ids for
your own programs, but they will probably die a slow (or fast) painful death
because the system will also continue to send them to you as well, passing the
parameters that it says are correct for them. This will certainly cause
crashes. You can, and will, sometimes fake system messages to your own windows
but that is a special case and you must carefully emulate the parameter
conventions of the system message you are faking.
One common case is for WM_SIZE messages. Many window procedures will have very
special code that is run when it gets a WM_SIZE, which will calculate the sizes
of its various parts and store them away. However a window does not get sent a
WM_SIZE message when it's first created; I assume because it is already told
how big it was in the WM_CREATE. Since the size code is in WM_SIZE, to avoid
pulling the code out to a separate function, you can just have WM_CREATE send
itself a WM_SIZE message to cause that code to correctly calculate everything
for the initial size. The initial window size is passed in the PCREATESTRUCT
parameter of WM_CREATE.
PM defines a value, WM_USER, above which all user messages must be placed. So
you always define your own user defined messages as WM_USER+x, where x is some
relative displacement value.
Incoming/Outgoing
One common area of misconception is that all windows in a program must have
different user defined message or problems will occur because of
misinterpreting a window message. But this is only partly true, and is driven
by the direction of the message. All windows can define ids, for the messages
that they want others to send to them, any way they want without worries of id
clashes (because they are the only class of window which will receive them.)
Sure there is the pathological problem of a window sending a message to the
wrong window, but that is inherent in the looseness of such a message passing
architecture. The situation is not significantly improved by going through all
the trouble of insuring unique incoming message ids.
When messages are sent out from a window or subsystem to other windows, then
the situation is different. Since the sending window cannot know what incoming
message ids are used by other windows, steps must be taken to insure
uniqueness. If the message is being sent out of some subsystem, a registration
mechanism is often possible in which a client program registers what messages
it wants sent to it. I've used this a number of times. In situations where
messages must be transmitted to foreign process, third party, or otherwise
uncontrolled windows for which the registration mechanism might not be
feasible, the only solution is often to create a system atom. The system atom
table is a mechanism for creating guaranteed unique values within the system.
This atom can them be used to create a unique outgoing message id.
The catch of using atoms is that they are no longer compile time constants and
therefore cannot be used as cases in the usual window procedure switch
statement. So you either have to check for them in default case of the switch
or via a set of if-then- elseif blocks prior to entering the main switch
statement. And, of course, the parties involved must agree on the atom by
either passing it along or having a common atom name which they can all look up
on startup. Window Relationships
I guess that the writers of most OS/2 documentation assume that the
relationships of windows to one another are so obvious that they don't need to
say the obvious things about them. But, there are a couple of often
misunderstood issues surrounding window relationships.
Basically there are two defined relationships between windows, parentage and
ownership. However, these two relationships are not on the same level at all.
Of the two parentage is the one that is most important and 'built into' PM.
Ownership is more of an artificial relationship that was created to deal with a
common GUI problem.
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.11. Window Parentage ΓòÉΓòÉΓòÉ
Window Parentage
Every window in PM except for the magical desktop (HWND_DESKTOP) and object
(WM_OBJECT) windows have parent windows. This is a required relationship that
always exists, though the parent of a window may be changed as desired.
Parenthood implies these facts:
All windows are placed relative to their parent window. When you query
or set a window's position, that position is relative to the lower left
corner of its parent window.
Since windows cannot exist without a parent, they are destroyed when
their parent is destroyed. This is both a convenience and a necessity.
When a window gets a WM_DESTROY, its child windows still exist so that
they can be queried, their size/position saved, etc....
When a window gets its WM_CREATE message it cannot have any child windows
because no one could have created any yet (other than PM itself who
won't). The window handle is not returned from WinCreateWindow() until
WM_CREATE processing is completed, so no one has had access to the window
in order to create a child window for it or assign one to it.
Child windows will never show outside of their parent windows because
they clipped to it. This is a natural effect of PM and does not require
any special effort on your part.
WinQueryWindow(hwndChild, QW_PARENT) cannot fail if hwndChild is a valid
window because it must have a parent to exist. There might be some
pathological multi-threaded situation where the query is made while the
switch is occurring.
Parenthood of a window can be changed using the WinSetParent() API. This API
is used often by PM to control, for instance, menus which often must appear
and disappear on demand. Instead of rebuilding them every time, their parent
is set to HWND_OBJECT, which hides them without affecting their size/position
information. You can use this scheme yourself to say display one of a set of
windows in a particular area of your client screen according to some
circumstance. Be aware that, when you do this, those windows will not be
destroyed automatically when your client is destroyed now because automatic
destruction only occurs for child windows. So you must generally track them
by window handle so you can destroy them when you get a WM_DESTROY message.
You cannot use ids to find them because any process can have windows under
HWND_OBJECT, some of which could have your same id. Another exception to this
rule is that frame windows will destroy all of their child windows (naturally
like everyone else does) plus all of their owned windows. This makes sure it
gets all of those windows cleaned up successfully.
Window Ownership
Whereas window parentage is a somewhat 'physical' relationship, ownership is
more of a 'legal' relationship. In PM, when a user interacts with a control
window, that window will send a WM_CONTROL message to its owner window. In an
object oriented system, this would have probably worked the other way where
control windows would handle their own events in an extendable way via
polymorphism; but, in a non-OOPs system, the most practical way to provide
extensibility of the standard controls is to let the client code respond on
their behalf as suits the application's particular circumstances. Given that,
there arose the need to know 'who' was interested in these events. Therefore
an artificial relationship of ownership was invented, so that a 'legal
contract of notification' could be arranged between two windows. Ownership is
not affected by the parenthood heirarchy at all, so a window's owner could
possibly be almost any other window.
Since this relationship is more artificial, it can be ignored totally (i.e. a
window is not required to have an owner) and it can be used by custom window
classes to represent some other type of legal contract. The (almost) only
reason it is magical at all is because WinQueryWindow() allows a window's
owner to be queried. But you could easily arrange to provide other
relationships between your own windows if you wish to do so. It would be more
work than ownership because you would have to provide your own internal
mapping tables or store a reference to the other window inside each window.
But it would be just as 'legitimate' a relationship as ownership.
Ownership can be changed or set via the WinSetOwner(). It can be set to 0, to
make the window no longer have an owner. This might be a convenient way to
make child controls 'shut up' for extended periods of time when the owner is
not prepared to deal with them.
Note that the ownership relationship is used (just for confusion's sake) for a
couple things other than the event notification. Presentation parameters can
be inherited via the ownership chain and frame windows have an option to be
moved relative to their owner. This allows them to float outside their parent
but maintain the same position relative to it. Also, frame windows minimize
their owned windows when they are minimized and destroy their owned windows
when they are destroyed, which is unlike any other window class.
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 8.12. Summary ΓòÉΓòÉΓòÉ
Summary
I hope this quick tour of OS/2's rougher surfaces has helped some. I realize
that this article jumps around somewhat erratically and that most of these
subjects could each be extended to fill a full book chapter in order to cover
all of their details. But this overview should hopefully give you a leg up on
some of the problem areas and some potential areas of improvement in your code.
And besides, I would not have any time to actually write any code and would
have nothing to write about next time. Hopefully I will be able to expand upon
some of these topics in subsequent issues.
If you have any questions or need amplication of any of these issues feel free
to drop me a line to droddey@jaguNet.com or, on Compuserve, at id 72170,1614.
Have fun with PM, but don't put your eye out with that thing!!
OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 9. /dev/EDM2/BookReview ΓòÉΓòÉΓòÉ
/dev/edm2/BookReview
Written by Carsten Whimster
Introduction
In /dev/EDM2/BookReview, I focus on development books and materials. I have
written this column from the point of view of an intermediate PM C programmer
and intermediate REXX programmer. Pick up whichever book strikes your fancy,
and join the growing group of people following our PM programming columns. I
have already reviewed a number of beginner's books, and will try to concentrate
a bit more on intermediate techniques and special topics from now on.
Please send me your comments and thoughts so that I can make this column as
good as possible. I read and respond to all mail.
The OS/2 Certification Handbook is a book that is designed to prepare you for
the OS/2 Certified Engineer tests.
/dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 9.1. Errata ΓòÉΓòÉΓòÉ
Errata
My Web page is still growing, and has recently had over 2700 hits. Perhaps my
joke about using 5 digits for my hit-counter is not a joke after all. At this
pace, it may hit 10000 by Christmas. Luckily, I won't need 6 digits for a
while. Check it out at <URL:http://www.undergrad.math.uwaterloo.ca/~bcrwhims/>.
<plug warning> My POV-Panel/2 has recently gone golden, and the release is
called 1.1a and is available on my web page, as well as on ftp.cdrom.com, and
hobbes.nmsu.edu. Once I started getting registrations, I realized that I was
not terribly well qualified to answer complicated questions about why my
program wasn't working on certain real-world setups, and so I looked into this.
This culminated in the purchase ($$$) of this month's book. If you are
interested in ray-tracing, use POV-Ray, and sometimes write your own scripts,
you definitely want to take a look at this program. </plug warning>
Partition Magic from Power Quest has to be one of the most timely programs to
ever be released. I have just assisted several friends in installing OS/2, and
in each case I am not sure if they would have installed it if they had not been
able to move partitions around, grow them, shrink them, and convert them. This
may be one of OS/2's strongest points. It is now available in a DOS/Windows
version too, but it was originally an OS/2 program. Partition Magic definitely
makes it easier to try OS/2 without nuking your current setup, which may be
enough to convince more people to switch. Of course, when the next release of
your favorite C/C++ compiler is released, you may well find that your
development partition is too small to hold it. What better time to get a new
harddrive, and resize partitions <grin>
/dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 9.2. OS/2 Certification Handbook ΓòÉΓòÉΓòÉ
OS/2 Certification Handbook
OS/2 Certification Handbook may seem like an odd fit for these pages. The
reason that I am reviewing it is that I needed some of the information in it to
properly support my shareware program. I was getting strange questions, the
answers for which I had never come across, and it quickly became apparent that
I needed a more authoritative command of all things OS/2. Hence the purchase
(and quite a hefty one at that) of this book. The way I see it, most shareware
authors, of which I am sure we have quite a few as readers, could use this
information to support their products. Here are the chapter titles:
Part One: Installation
1. Versions of OS/2
2. Planning for Installation
3. Installing OS/2 Warp, Version 3
4. Installing OS/2 2.1
5. Advanced Installation Tips
6. Printer Installation
7. Font Installation
8. Control Files
9. Installing and Migrating Applications
Part Two: Using OS/2
10. Understanding OS/2 Concepts
11. Performing Basic Operations
12. Manipulating Windows
13. Getting Online Information
14. Using Desktop Objects
15. Using Menus and Notebooks
16. Using Advanced WPS Features
17. Understanding the File System
18. Running Applications
19. Installing Applications
20. System Startup
21. Printing
22. Customizing OS/2
23. Using the Workplace Shell Efficiently
Part Three: Supporting OS/2
24. Support Tools
25. Software Aids
26. The Boot Process
27. Solving Video Problems
28. Solving Printer Problems
29. CONFIG.SYS
30. Error Recovery
31. System Dumps
Part Four: OS/2 Performance and Tuning
32. Understanding OS/2 Memory and Task Architecture
33. Measuring Performance
34. Maximizing Performance
35. Understanding Other Performance Issues
Part Five: Appendixes
A. Using the Keyboard
B. Help via Modem and Fax
C. Maintenance
D. Understanding REXX
Part Six: Command Reference
Command Reference
Again this month, I will concentrate on the sections, rather than the chapters,
since the divisions between the chapters are less important than in programming
books. In addition, this book is absolutely immense, and reviewing it in any
kind of detail in one month is impossible.
Part One covers various installation issues, including new features in Warp, a
planning section for installation, which includes checking out the system
requirements for the intended usage versus the actual requirements available, a
detailed section on configuration decisions, such as whether or not to use
HPFS, how to arrange partitions, and whether or not to use Boot Manager. This
is followed by a small section that outlines what DOS and Windows programs OS/2
can support, and how. Finally in chapter two there is a brief run-through of
the amount of space required for the various selectable components, and when it
makes sense to leave out components. At the end of every chapter there is a
small questionnaire which tests how well you have read and retained the
information offered in that chapter. This is not always as easy as it sounds!
Chapters three and four describe the actual installation in detail, for Warp
and OS/2 2.1, respectively. Both the easy installation and the advanced
installation options are covered for Warp. Installing OS/2 2.1 (for those of us
that remember) is actually nearly identical to installing Warp, except that it
has gotten easier, and there are now a few more options along the way, and a
lot more drivers. Advanced installation topics are the subject of chapter five.
Oddly enough, the first sentence reads "Wrapping up the installation section of
this book, this chapter covers...". Considering that the installation section
covers chapters one through nine, this statement is a little premature.
Occasionally, I get the distinct impression that this book is a changed version
of an earlier book, although I don't know which. Understanding OS/2's directory
structure, support options, and removing OS/2 is all explained here. There is
another small error in the support section. The newsgroups on the Internet are
claimed to start with comp.os2 whereas they in fact all start with the
comp.os.os2 prefix.
The next chapter discusses printer considerations. This includes a discussion
of the flow through the system of the print job, printing in DOS, printing in
WIN-OS/2, pooling, spooling, and installation. Chapter 7 deals with fonts. It
starts with a section describing the terminology of fonts, and continues
through installation, and fonts in WIN-OS/2. Chapter eight covers "control
files". This includes the obvious INI files, the CONFIG.SYS, and STARTUP.CMD,
but covers everything only in light detail. These topics will be revisited in
another section. Finally, chapter nine covers installing and migrating
applications. A brief tour through the various memory types and requirements,
video support for DOS and Windows, and VDM settings ends up in installing and
migrating the applications, and creating program objects for them. Modifying
the migration database is also covered.
The second part, called "Using OS/2," is a fair amount larger, and I will not
mention the chapters explicitly, but rather cover only the topics of most
interest to us, as OS/2 professionals. This section discusses objects and the
WPS. It enforces a rigid understanding of the object paradigm, including both
how to set them up, and how to manipulate them. Getting help on the use of
certain objects is covered, the settings notebooks are explained, customization
of objects, the file system's relationship to objects, and printing and objects
are all explained. The various object types are covered early on. The various
window components are explained, but this should be old hat to most OS/2
programmers. Most of the stuff covered is done so in excruciating detail, but
every once in a while, there is a little gem of information which you didn't
know before, and which clears up something that happened once in the past. At
other times there is very little on some subject. The new feature "pickup" is
explained. Here is a feature which is potentially quite useful, but which I bet
very few people actually use. DDE between applications is also touched on.
Sometimes it is surprising how little detail there is on some subject or other.
Considering the thickness of the book, it may seem a little odd, but when you
check, there is actually something written on every page, and so I guess they
must have run out of room for certain minor things. Chapter 23 is one of the
more interesting chapters. Entitled "Using the Workplace Shell Efficiently", it
has a definite emphasis on contrasting various features for the purpose of
enabling you to choose the one you prefer. Again, this chapter seems a little
short on explanations.
Part three is the one of most interest to me personally, and is in fact the
part that I bought the book for. "Supporting OS/2" is of immediate importance
to any shareware or commercial OS/2 programmer. How many times have we heard
"it doesn't work on my system", and then had to (sometimes remotely) analyze a
system only to find out that a certain option, or replacement program isn't
100% compatible. 4OS2 falls into this latter category for me. Great program,
but careful how you use it. It doesn't have a "start" command, for example, so
don't make it your default shell unless you know that you don't need this
feature. I had trouble with this in my POV-Panel/2. It uses the "start" command
to launch POV-Ray. The resulting error took me a month to figure out! In the
future, I want to be better at this type of thing, hence this book.
First, the various types of built-in documentation are explained. Besides this,
there are several files and tools mentioned which are available through IBM's
BBSes. How would you find out about these tools without this book, without
spending tons of time browsing the net, trying out tools and programs? I don't
know. Yet this is how they recommend that we proceed. So be it. Some tools are
outlined next. The boot process is explained in a little more detail than
usual, including the POST, BIOS/CMOS, and OS/2 itself. Video problems are next,
followed by printer problems. Following this is an immensely helpful chapter on
the CONFIG.SYS, including what many of the parameters mean, and what they do.
The actual tuning comes later, but this chapter really helps the comprehension
of this text-based dinosaur fragment in OS/2. The following chapter is also a
great help, but in a different way. It treats recovery from terrible events,
and how to prepare. It includes brief explanations of some of the tools, such
as tedit, bootos2, and other EWS programs. Diagnosing is another useful
sub-heading of this chapter. The level of detail isn't great, though. System
dumps is an OS/2 feature I have never used. Actually, I did do a dump once, but
then I had no tools to analyze the dump, so I deleted it. Chapter thirty-one
discusses dumps briefly.
Part four is about performance and tuning, and I am sure that there is no area
of OS/2 which involves more black magic than this. Everyone seems to have their
own opinion of what works best, so it is refreshing to have official advice.
What is more important than just making changes, this section explains how to
measure performance differences, and thus effectively lets anyone try anything
they want, without fear that they have inadvertently slowed down their system
without knowing it. For us OS/2 professionals (you are going to get very tired
of me saying that <grin>), there is a certain pride, but also practical value,
in having a well-tuned system. Everything from the CPU to multi-tasking and
applications is discussed. Many OS/2 features which are used by programmers are
discussed, such as semaphores, signals, pipes and so on. Inherent features of
the O/S itself, such as virtual memory, I/O, and file systems are also
discussed. All of this is followed by practical ways of measuring performance.
This includes using "pulse", SPM/2 (available from IBM), and creating your own
tool. Both installation-time options and post-installation options are
examined. There is probably more meat on the why's of OS/2 in this section than
in any other single place, possible excluding OS/2 Warp Unleashed, and The
Design of OS/2.
The final part consists of appendixes (appendices?) only. The REXX appendix is
quite informative, and includes a mini-reference, but it is a bit short. The
other three chapters are even shorter. The book is wrapped up with a command
reference, and a good index.
/dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 9.3. Summary ΓòÉΓòÉΓòÉ
Summary
This book is not a programmer's book, but it is a book for the aspiring
self-employed software company CEO <grin>. It teaches long and hard lessons
about the intricate details of OS/2, both OS/2 2.1 and Warp. Installing, using,
and supporting OS/2 are all taught well, and apart from a few unfortunate
errors, it is all quite accurate. For any reasonably well-versed OS/2 user,
between 50 and 75 percent of the material will not be new, but the remaining 25
to 50 percent would be very hard to learn on your own. It is a very expensive
book, but it is very large (over 1000 pages) and well worth it. I rate this
book an A-, due to the errors and occasional omissions.
/dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 9.4. Book Reviewed ΓòÉΓòÉΓòÉ
Book Reviewed
OS/2 Certification Handbook, Hallberg and Ivens
- New Riders Publishing. ISBN 1-562-05407-4. US$89.99, CAN$122.95
- OS/2 Professionals
- A-
This certification primer is full of information, much of it trivial, much of
it worth its weight in gold. It comes with a CD including sample tests. This
book is recommended to OS/2 programmers who like to think of themselves as more
well-rounded OS/2 professionals, rather than just coders, and anyone thinking
of taking a crack at programming and supporting OS/2 for a living. You could
follow up the book with the OS/2 Certified Engineer tests, but this is not
necessary.
NOTES
Please note that books aimed at different audiences should only be compared
with great care, if at all. I intend to concentrate on the strong points of the
books I review, but I will point out any weaknesses in a constructive manner.
LEGEND
BOOK: The name of the book, and the author(s)
PUBLISHING INFORMATION: Publishing company, ISBN, and approximate price.
AUDIENCE: This is a description of the audience I think the book targets best.
This is not intended as gospel, just a guideline for people not familiar with
the book.
MARK: My opinion of the success of the book's presentation, and how well it
targets its audience. Technical content, accuracy, organization, readability,
and quality of index all weigh heavily here, but the single most important item
is how well the book covers what it says it covers. Many books try to cover too
much, and get a lower mark as a result.
A+ Ground-breaking, all-around outstanding book
A Excellent book. This is what I want to see happen a lot
A- Excellent book with minor flaws
B+ Very good book with minor flaws or omissions
B Good book with some flaws and omissions
B- Good book, but in need of improvement
C+ Mediocre book with some potential, but in need of some updating
C Mediocre book with some good sections, but badly in need of fixing
C- Mediocre book, little good material, desperately in need of an overhaul
D Don't buy this book unless you need it, and nothing else exists
F Don't buy this book. Period
COMMENTS: This is a very brief summary of the review proper.
/dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 9.5. Index ΓòÉΓòÉΓòÉ
Index
This Content Index is designed to let you find the book that covers the topics
you need to learn about. It will eventually have a lot of categories, with each
book being rated along each row. These tables will be quite large, and will
continually grow, so please give me your feedback regarding what categories you
would like to see, and which you don't. It may take me a while to flesh them
out, so have a little patience.
BOOK LEGEND:
code issue title
RWP 2-3 Real World Programming for OS/2 2.1
LPE 2-4 Learning to Program OS/2 2.0 Presentation Manager by Example
ODD 2-5 Writing OS/2 2.1 Device Drivers in C
GPI 2-6 OS/2 Presentation Manager GPI
TAO 2-7 The Art of OS/2 2.1 C Programming
MOR 2-8 Mastering OS/2 REXX
RSH 2-9 REXX Reference Summary Handbook
ADO 2-10 Application Development Using OS/2 REXX
PMP 2-11 OS/2 Presentation Manager Programming
DOA 3-1 Designing OS/2 Applications
OSP 3-2 OS/2 Programming
TGO 3-4 The GUI-OOUI War
OU 3-5 OS/2 Warp Unleashed, Deluxe Edition
QR1 3-6 WIN Functions, OS/2 Quick Reference Library Volume 1
PWG 3-7 Programming the OS/2 Warp Version 3 GPI
DHP 3-8 Designing High-Powered OS/2 Warp Applications
OCH 3-9 OS/2 Certification Handbook
NOTE: Books which cover the same material can look similar in this table, but
be different in real life. The style of a book, for example, can not be seen
from a quick table, so make sure that you follow up by reading the reviews of
the books you find here. Finally, be sure that the books you are comparing are
aimed at the same audiences.
PM C BOOKS:
BOOK MARK Kernel Device VIO/ PM GPI Fonts Print
Basics Driver AVIO
RWP B+ 2 0 0 4 4 4 3
PME B- 1 0 0 2 2 2 0
ODD A 0 5 0 0 1 0 1
GPI C+ 0 0 0 0 5 2 3
TAO B+ 3 2 1 4 1 2 0
PMP A- 1 0 1 5 3 4 2
OSP B+ 2 0 0 3 2 1 0
QR1 A 0 0 0 5(WIN) 0 0 0
PWG A- 0 0 0 1 5 5 5
REXX BOOKS:
BOOK MARK REXX WPS Reference
Intro
MOR B 4 0 2
RSH A 1 2 5
ADO A- 3 2 4
SYSTEM AND NON-PROGRAMMING BOOKS:
BOOK MARK Kernel Device VIO/ PM Thread GPI Fonts Print WPS
Basics Drivers AVIO
DOA A 4 4 2 4 5 3 2 3 1
TGO B 0 0 0 2 1 0 2 1 5
OU A+ 1 4 4 5 2 5 5 5 5
DHP A 4 4 2 4 5 3 2 3 1
OCH A- ? ? ? ? ? ? ? ? ?
RATINGS LEGEND:
0 No coverage
1 Very light coverage
2 Introductory coverage
3 Good Coverage
4 In-depth coverage
5 Authoritative
/dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 9.6. Coming Up ΓòÉΓòÉΓòÉ
Coming Up
I have here a trilogy of Warp API reference manuals, which I will review for
next month (I said that last time, but I lied). Other books I would like to
review are:
OS/2 Presentation Manager GPI, 2nd edition, Winn
The Design of OS/2, 2nd Edititon, Kogan and Deitel
If anyone has a book they want to see reviewed, I will be happy to oblige. Just
mail me and tell me. Publishers can send me books at the address on my personal
page at the end of the magazine, and I will review all OS/2 development-related
and advanced user books I receive.
/dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 10. Introduction to PM Programming ΓòÉΓòÉΓòÉ
Introduction to PM Programming
Written by Larry Salomon, Jr.
Introduction
The purpose of this column is to provide the readers out there who are not
familiar with PM application development the information necessary to satisfy
their curiosity, educate themselves, and give them an advantage over the
documentation supplied by IBM. Of course, much of this stuff could probably be
found in one of the many books out there, but the problem with books in general
is that they don't answer the questions you have after you read the book the
first time through.
I will gladly entertain feedback from the readers about what was "glossed over"
or what was detailed well, what tangential topics need to be covered and what
superfluous crap should have been removed. This feedback is essential in
guaranteeing that you get what you pay for. <grin>
It should be said that you must not depend solely on this column to teach you
how to develop PM applications; instead, this should be viewed as a supplement
to your other information storehouses (books, the network conferences, etc.).
Because this column must take a general approach, there will be some topics
that you would like to see discussed that really do not belong here. Specific
questions can be directed to me via email and I will do my best to answer them
in a timely fashion.
Where Are We?
As I sat down to write this month's installment, I had to look back to see
where we've been. The window classes that we've covered here so far are listed
below:
Button (WC_BUTTON)
Entryfield (WC_ENTRYFIELD)
Listbox (WC_LISTBOX)
Menu (WC_MENU)
Static (WC_STATIC)
Titlebar (WC_TITLEBAR)
The window classes left to be covered are listed below:
Circular slider (WC_CIRCULARSLIDER)
Combo box (WC_COMBOBOX)
Container (WC_CONTAINER)
Frame (WC_FRAME)
Multi-line edit (WC_MLE)
Notebook (WC_NOTEBOOK)
Scroll bar (WC_SCROLLBAR)
Slider (WC_SLIDER)
Spin button (WC_SPINBUTTON)
Value set (WC_VALUESET)
As I looked, I decided that we could hit three birds with one stone if we
ventured into the realm of the circular slider, slider, and scrollbar, since
all three controls are very similar in function.
Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2
ΓòÉΓòÉΓòÉ 10.1. Purpose ΓòÉΓòÉΓòÉ
Purpose
What is the purpose of each of these three controls? To sum it up in one
sentence, their purpose is to allow the user to choose a single value within a
range of values. Since Salomon's Law states that the complexity of a window
class is exponentially proportional to the number of words in which you can
state its purpose, you can imagine that we won't need to spend much time on
these controls.
Breakdown
If you breakdown the capabilities of the controls, you will see that all three
provide the following:
Set / Query the range of values
Set / Query the current value
Notify the owner when the value changes
We will look at the details specific to each control in this column starting
with the scroll bar (WC_SCROLLBAR).
Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2
ΓòÉΓòÉΓòÉ 10.2. Scroll Bar Terminology ΓòÉΓòÉΓòÉ
Scroll Bar Terminology
The parts of a scroll bar are labelled in the illustration below.
The buttons are used to change the position by one increment (see below).
The slider areas are used to change the position by one page.
The thumb is used to move the scroll bar to an absolute position.
The concept of a unit or a page of units is defined by the application. One
unit may correspond to one line of text, but it may correspond to three lines
of text.
Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2
ΓòÉΓòÉΓòÉ 10.3. Scroll Bar Styles ΓòÉΓòÉΓòÉ
Scroll Bar Styles
The scroll bar styles are listed below.
SBS_AUTOSIZE - The PM Guide and Reference states that this style causes
the scroll bar to automatically change its size to reflect the amount of
data contained in the window. I have never seen the style used before
and there is no documentation on its use, so we will not discuss this
further.
SBS_AUTOTRACK - Like SBS_AUTOSIZE there is no documentation on this
style. The PM Guide and Reference states that this style causes the
scroll bar to automatically scroll as more information is being displayed
on the screen.
SBS_HORZ - This style creates a horizontal scroll bar.
SBS_THUMBSIZE - This style indicates that a scroll bar control data
(SBCDATA) structure is being passed in as the second-to-last parameter to
WinCreateWindow() and that the cVisible and cTotal fields are
initialized.
SBS_VERT - This style creates a vertical scroll bar.
Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2
ΓòÉΓòÉΓòÉ 10.4. Scroll Bar Notifications ΓòÉΓòÉΓòÉ
Scroll Bar Notifications
The scroll bar is unlike the other PM controls in that its notifications are
not communicated via the WM_CONTROL message. Instead, depending on the
orientation of the scroll bar (horizontal or vertical), the owner receives a
WM_HSCROLL or WM_VSCROLL message.
WM_HSCROLL / WM_VSCROLL
SHORT1FROMMP(mpParm1) - specifies the ID of the scroll bar.
SHORT1FROMMP(mpParm2) - specifies the position of the scroll bar. This is 0 if
the keyboard is being used to move the scroll bar.
SHORT2FROMMP(mpParm2) - notification type:
SB_LINELEFT - the left arrow was clicked with the mouse or the left arrow
key was pressed.
SB_LINERIGHT - the right arrow was clicked with the mouse or the right
arrow key was pressed.
SB_LINEUP - the up arrow was clicked with the mouse or the up arrow key
was pressed.
SB_LINEDOWN - the down arrow was clicked with the mouse or the down arrow
key was pressed.
SB_PAGELEFT - the slider was clicked to the left of the thumb with the
mouse or the page up key was pressed.
SB_PAGERIGHT - the slider was clicked to the right of the thumb with the
mouse or the page down key was pressed.
SB_PAGEUP - the slider was clicked above the thumb with the mouse or the
page up key was pressed.
SB_PAGEDOWN - the slider was clicked below the thumb with the mouse or
the page down key was pressed.
SB_SLIDERPOSITION - this is sent to indicate the final position of the
scroll bar.
SB_SLIDERTRACK - if the mouse is being used to "drag" the thumb, this is
sent every time the position changes.
SB_ENDSCROLL - this indicates the end of scrolling and is sent only if
the thumb was not dragged.
Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2
ΓòÉΓòÉΓòÉ 10.5. Scroll Bar Messages ΓòÉΓòÉΓòÉ
Scroll Bar Messages
There are five, easy to understand messages that the scroll bar understands:
SBM_QUERYPOS
This message returns the current position.
SHORT1FROMMR(mrResult) - current position.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
SBM_QUERYRANGE
This message returns the current scroll bar range.
SHORT1FROMMR(mrResult) - lower bound of the range.
SHORT2FROMMR(mrResult) - upper bound of the range.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
SBM_SETPOS
This message sets the current position.
SHORT1FROMMP(mpParm1) - new position.
SHORT1FROMMR(mrResult) - success indicator (BOOL).
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
SBM_SETSCROLLBAR
This message sets the current position and the range.
SHORT1FROMMP(mpParm1) - new position.
SHORT1FROMMP(mpParm2) - new lower bound of the range.
SHORT2FROMMP(mpParm2) - new upper bound of the range.
SHORT1FROMMR(mrResult) - success indicator (BOOL).
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
SBM_SETTHUMBSIZE
This message sets the size of the thumb. It is used to indicate to the user
how much of the data is viewable at a time.
SHORT1FROMMP(mpParm1) - visible amount of data.
SHORT2FROMMP(mpParm1) - total amount of data.
SHORT1FROMMR(mrResult) - success indicator (BOOL).
Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2
ΓòÉΓòÉΓòÉ 10.6. Next Month ΓòÉΓòÉΓòÉ
Next Month
Next month we will take a look at a small application that uses both the
horizontal and vertical scroll bars to allow you to scroll through a "large"
amount of data. Bring your thinking caps!
Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2
ΓòÉΓòÉΓòÉ 11. OOPS Avenue ΓòÉΓòÉΓòÉ
OOPS Avenue
Prolog
Well Larry finally thought it was safe to let me do an editorial section as a
preface to the column. So with out further adieu, here we go.
I was going to start this new section off with a bang by dragging Watcom's
technical support system through the coals. A general rule is never write
anything that you intend to have someone else read while your angry. During
the cool down period, much to my surprise, I received a phone call from Watcom
tech support, explaining the initial lousy support I had received. Although
tech support couldn't offer any solution, the bug which I had reported was
confirmed to be a known problem that affects only some people for unknown
reasons. In the Watcom 10.5 compiler review, you will notice that I mentioned
the debugger didn't debug PM programs.
After trying to compile a public domain C++ package with Watcom, Metaware and
C-Set++ 2.1, I suddenly realized just how buggy C++ compilers are. Each one of
the three compilers complained about a different section of the code. With
Metaware and Watcom it was problems with templates. With C-Set++, it was an
incredibly strange interpretation of access permissions. After some hacking
about with the code, it finally compiled cleanly on all 3 compilers. Hopefully,
when compiler vendors start writing to the ANSI C++ specification, these
problems will start disapearing.
OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 11.1. Introduction ΓòÉΓòÉΓòÉ
Introduction
Direct To SOM (DTS) is the easiest way to write a SOM object. A DTS compiler
compiles code in its native language (i.e. C++) into a SOM compatible module.
The two DTS C++ compilers for OS/2 are Metaware High C/C++ and Visual Age C++.
This article will use the Metaware compiler. However, IBM's DTS #pragma syntax
will be used so this examples should (in theory) compile under VAC.
The use of DTS will be illustrated by designing a simple screen saver object.
In this issue, we will design an OOP saver module in C++, and DTS. The OOP
method will then be compared to a conventional non-OOP approach.
OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 11.2. A C++ Saver Object ΓòÉΓòÉΓòÉ
A C++ Saver Object
Before we can design an object, we have to decide what properties the object
needs. We need to be able to toggle the saver object in and out of saver mode,
and possibly display some setup information. The following C++ object could
serve as the base for our hierarchy.
class SaverBase{
public:
SaverBase();
~SaverBase();
virtual void StartSaver()=0;
virtual void StopSaver()=0;
virtual void DisplaySetup(){}
};
To implement a specific screen saver, we would subclass SaverBase and implement
the two pure virtual member functions. We could even create a non-member
function to create a specific class and then package each child of SaverBase in
a DLL. This would allow us to add new saver types without recompiling the
code. However, anyone wanting to write new saver modules would have to use the
exact same C++ compiler as we used. The need to use the exact same compiler
severely limits the usefulness of using a C++ based OOP approach.
OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 11.3. A DTS Saver Object ΓòÉΓòÉΓòÉ
A DTS Saver Object
The best part of using a DTS based approach is that we can write C++ code and
let the compiler worry about the SOM details. There are a few differences
between DTS C++ and native C++. These differences are listed in the DTS
section of the DTS compiler. Thus, we won't go into them here unless they
directly affect the example.
Various aspects of how the C++ object is converted into a SOM object are
controlled by pragmas. The pragmas in the following DTS based saver class are
numbered. These numbers will be used when explaining what each pragma does.
#pragma SOMAsDefault(on) //(1)
class SaverModule{
#pragma SOMClassVersion(*,1,1) //(2)
#pragma SOMNoMangling(on) //(3)
#pragma SOMClassName(*,"SaverModule") //(4)
public:
SaverModule();
~SaverModule();
virtual int GetNumPages();
virtual void ActivateSaver();
virtual void DeactivateSaver();
#pragma SOMNoMangling(pop) //(5)
#pragma SOMReleaseOrder(GetNumPages(),ActivateSaver(),DeactivateSaver(),operator=) //(6)
private:
};
#pragma SOMAsDefault(pop) //(7)
#pragma Number Effect
1 Turn on C++ -> SOM mode. Any C++ object declaration
occurring after this pragma will be assumed to be a DTS
object.
2 Specify the class version numbers.
3 Turn off name mangling. This makes it easier for non-DTS
programmers to extend this object in the language of their
choice.
4 Specify the name of the SOM class. To avoid mangling the
SOM classes name, we specify the name the DTS compiler is
to use.
5 Restore name mangling to its setting before pragma number
3. This is done so that the DTS compiler doesn't create a
"__as" function in the .idl. The leading "_" cases the
SOM compiler (sc) to generate a bunch of error messages.
6 Specify the release order for the functions. Note: the
default constructor and destructor are automatically
included in the release order so they don't have to be
included. Also note that operator= is automatically
generated by the DTS compiler.
The DTS object "SaverModule", closely resembles the C++ saver module. There
are functions to start and stop the saver, and one to get the number of setup
pages for the module. Assuming we were to implement the configuration of the
saver modules in a notebook, we would need to be able to query the number of
pages and the page handles from the module. For now, we'll ignore the issue
of configurability. We'll explore this issue in more detail when we revisit
the design in subsequent issues.
One of the best features of C++ DTS compilers is the ability to easily mix C++
and DTS objects. In the following example, we subclass SaverModule to
illustrate how a saver type can be created. We will use a C++ thread library
to implement the threading of the DTS object. The following DTS object
illustrates how a saver object would work and how to mix C++ objects with DTS
objects.
#pragma SOMAsDefault(off)
#include <ThreadTemp.h>
#pragma SOMAsDefault(pop)
#include "Saver.hh"
#pragma SOMAsDefault(on)
class TestSaver : public SaverModule{
#pragma SOMClassVersion(*,1,1)
#pragma SOMNoMangling(*)
#pragma SOMClassName(*,"TestSaver")
public:
TestSaver();
~TestSaver();
int GetNumPages();
void ActivateSaver();
void DeactivateSaver();
#pragma SOMNoMangling(pop)
private:
void ThreadFnc(void);
ClassThreadwoArg<TestSaver>
TestThread; //(1)
int SaverActive;
};
#pragma SOMAsDefault(pop)
When ActivateSaver is called, TestThread is started. While the saver is
active, it writes '.' to stdout. The interesting part about this example, is
that a C++ object is a member of a DTS object and that a DTS object is used as
the "type" of a C++ template object (see number 1 in the above source). Below,
we see that using a DTS object is the same as using a C++ object.
#include <io.h>
#include <conio.h>
#include <iostream.h>
#include "TstSave.hh"
int main(){
SaverModule *Saver;
cout<<"Press Enter to start saver"<<endl;
getch();
Saver=new TestSaver;
Saver->ActivateSaver();
(cout<<"Press Enter to stop saver"<<endl).flush();
getch();
Saver->DeactivateSaver();
cout<<"Press Enter to destroy saver"<<endl;
getch();
delete Saver;
return 0;
}
Notice that in this example, we have to know about the object's "type" before
we can use it. This makes it impossible to add new saver types at run time.
However, SOM was designed to allow run time class resolution and much much
more. We'll explore run time class loading next. But before we move on, the
full source to this sample can be found in try1.zip.
To support run time loading, we have to put our objects into one or more DLLs.
In doing so, I stumbled into a Metaware bug. It seems one can't use the
threaded libraries with a DLL. If you try to use the multi-threaded
libraries, the DLL will trap on load. This required all the threading code to
be removed from the DTS objects.
The files main.cpp and maincpp.cpp illustrate that the DTS DLL is indeed
usable from 2 different languages/compilers. Below is the source code to
main.cpp, which illustrates dynamically loading a DTS object from a DTS
program.
#include <io.h>
#include <conio.h>
#include <iostream.h>
#include <som.hh>
#include <somcls.hh>
#include <somcm.hh>
//#include "Saver.hh"
#include "TstSave.hh"
int main(){
SaverModule *Saver;
cout<<"Press Enter to start saver"<<endl;
getch();
somId classId = somIdFromString("TestSaver"); //(1)
SOMClass *myClass = SOMClassMgrObject->somFindClsInFile(classId,
1, 1,"TstSave"); //(2)
SOMFree(classId); //(3)
Saver=(SaverModule *) myClass->somNew(); //(4)
// Saver=new TestSaver; //(5)
Saver->ActivateSaver();
(cout<<"Press Enter to stop saver"<<endl).flush();
getch();
Saver->DeactivateSaver();
cout<<"Press Enter to destroy saver"<<endl;
getch();
delete Saver;
return 0;
}
Note: even though "TstSave.hh" is included, it doesn't have to be.
The to dynamically load a SOM object, lines 1 through 4 replace line 5. To use
the DTS object with C++ bindings, simply change the ".hh" to ".xh" in the
include statements. The file try2.zip contains the source for the dynamic
loading sample
You're probably wondering where did these .xh files come from. To allow DTS
objects to be used from other languages, the DTS compiler can create .idl
files. Using the SOM compiler, one can create bindings for any language.
OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 11.4. The Non-OOP Method of Creating an Extendible Screen Saver ΓòÉΓòÉΓòÉ
The Non-OOP Method of Creating an Extendible Screen Saver
The term "Non-OOP" is misleading. Perhaps the a better term is informal OOP.
In essence what the developer is doing is using DLLs to implement a limited
form of data-abstraction. The developer defines a set of mandatory functions
that the DLL must implement. The screen saver executable then uses
DosLoadModule and DosQueryProcAddr to load and execute the saver functions.
In either of the OOP cases, the addresses of the saver functions aren't queried
by the saver executable. In the DTS version, saver modules themselves can be
subclassed to alter their behavior.
OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 11.5. Summary ΓòÉΓòÉΓòÉ
Summary
DTS is an easy way for someone familar with C++ to create SOM objects. It
allows one to easily mix C++ and SOM objects with each other. This allows the
best of both worlds: C++ can be used where raw speed is required, and SOM can
be used where binary independence is needed. In subsequent issues, I hope to
develop the DTS Screen saver into a working program.
OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 12. Contributors to this Issue ΓòÉΓòÉΓòÉ
Are You a Potential Author?
We are always looking for (new) authors. If you have a topic about which you
would like to write, send a brief description of the topic electronically to
any of the editors, whose addresses are listed below, by the 15th of the month
before the month in which your article will appear. This alerts us that you
will be sending an article so that we can plan the issue layout accordingly.
After you have done this, get the latest copy of the Article Submission
Guidelines from hobbes.nmsu.edu in the /os2/newsltr directory. (The file is
artsub.zip.) The completed text of your article should be sent to us no later
than five days prior to the last day of the month; any articles received after
that time may be pushed to the next issue.
The editors can be reached at the following email addresses:
Larry Salomon - os2man@panix.com (Internet).
Carsten Whimster - bcrwhims@uwaterloo.ca (Internet).
The following people contributed to this issue in one form or another (in
alphabetical order):
Marc Mittelmeijer
Dean Roddey
Larry Salomon, Jr.
Eric Slaats
Carsten Whimster
Gordon Zeglinski
Network distributors
Contributors - EDM/2 - Nov 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 12.1. Marc Mittelmeijer ΓòÉΓòÉΓòÉ
Marc Mittelmeijer
Marc Mittelmeijer studied mathematics at the faculty Mathematics and
Informatics at the Technical University of Eindhoven. Since 1984 Marc teaches
mathematics and information technology at the Hogeschool Eindhoven, Faculty
Economics Sr Business Informatics. Besides teaching he is researching the
behavior of neural networks in a financial environment.
Marc can be reached at M.Mittelmeijer@fe.hse.nl
Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 12.2. Dean Roddy ΓòÉΓòÉΓòÉ
Dean Roddey
Dean Roddey is a Senior Software Engineer at Quantitative Medicine, A Marquette
Electronics Company, in Annapolis MD. He is also the author of the CIDLib
Class Libraries, a C++ class framework for Warp and IBM's Visual Age C++
development environment. He can be reached at droddey@jaguNet.com or at
Compuserve id 72170,1614. Or check out his home page at
http://www.jagunet.com/~droddey/ to get more information on the CIDLib
libraries.
Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 12.3. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
Larry Salomon Jr.
Larry Salomon Jr. has been developing OS/2 applications since version 1.1 in
1989. He has written numerous applications, including the Scramble applet that
was included in OS/2 versions 2.0-2.11, and the I-Brow, Magnify, and Screen
Capture trio that has been distributed on numerous CD-ROMs.
Larry is also the coauthor of the successful book, The Art of OS/2 Warp
Programming (Wiley-QED). Finally, he is the CEO/President of IQPac Inc. which
is responsible for the publication of EDM/2 and he is a frequent contributor to
the publication.
Larry can be reached electronically via the Internet at os2man@panix.com.
Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 12.4. Eric Slaats ΓòÉΓòÉΓòÉ
Eric Slaats
Eric Slaats teaches information technology at the Hogeschool Eindhoven, Faculty
Economics Sr Business Informatics. Besides teaching he has written a number of
books. Currently he is researching the behavior of neural networks in a
financial environment. He started programming OS/2 PM to build an interface
for a Neural network problem in september 1994. He's the author of the Smalled
and Confed utilities.
Eric can be reached electronically via the internet at E.Slaats@fe.hse.nl
Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 12.5. Carsten Whimster ΓòÉΓòÉΓòÉ
Carsten Whimster
Carsten is an undergraduate Computer Science student at the University of
Waterloo. He is currently in fourth year, and enjoying it immensely. He uses
Watcom C/C++ 10.0a and Watcom VX-REXX 2.0c. Carsten is the author of some
commandline utilities, and POV-Panel/2. He is currently trying to learn enough
GPI programming to do a remake of the old video game Qix, but there are other
projects on the go too, such as converting POV-Panel/2 to PM, and writing a PM
ps type utility. Carsten is also a TEAM-OS/2 member, and has adopted a little
computer store called The Data Store in Waterloo, Ontario.
You may reach Carsten...
...via email (Internet):
bcrwhims@undergrad.math.uwaterloo.ca
...via the World Wide Web:
http://www.undergrad.math.uwaterloo.ca/~bcrwhims/
...via snail mail:
318A Spruce Street
Waterloo, Ontario
Canada
N2L 3M7
...via voice:
(519)886-2439
Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 12.6. Gordon Zeglinski ΓòÉΓòÉΓòÉ
Gordon Zeglinski
Gordon Zeglinski is a freelance programmer/consultant who received his Master's
degree in Mechanical Engineering with a thesis on C++ sparse matrix objects.
He has been programming in C++ for 6 years and also has a strong background in
FORTRAN. He started developing OS/2 applications with version 2.0 .
His current projects include a client/server communications program that
utilitizes OS/2's features which has entered beta testing. Additionally, he is
involved in the development of a "real-time" automated vehicle based on OS/2
and using C++ in which he does device driver development and designs the
applications that comprise the control logic and user interface.
He can be reached via the Internet at zeglins@cc.umanitoba.ca.
Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9
ΓòÉΓòÉΓòÉ 12.7. Network Distributors ΓòÉΓòÉΓòÉ
Network Distributors
These people are part of our distribution system to provide EDM/2 on networks
other than the Internet. Their help to provide access to this magazine for
others is voluntary and we appreciate them a lot!
Paul Hethmon (phethmon@utk.edu) - Compuserve
Gess Shankar (gess@knex.mind.org) - Internet
Jason B. Tiller (PeerGynt@aol.com) - America On-line
David Singer (singer@almaden.ibm.com) - IBM Internal
Jesper Nielsen (afdata@pop02.ny.us.ibm.net) - Denmark BBS's
If you would like to become a "network distributor", be sure to contact the
editors so that we can give you the credit you deserve!
Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9